def centrifugal_force(radius: Unit("m"), speed: Unit("Hz"), mass: Unit("g")) -> Unit("N"): """ Compute the centrifugal force of a [mass] rotation at [speed] at radius [radius] """ radius = normalize_numeric(radius) mass = normalize_numeric( mass) / 1000.0 # mass needs to be Kilograms TODO Improve return mass * angular_speed(speed)**2 * radius
def rotating_liquid_pressure(density: Unit("kg/m³"), speed: Unit("Hz"), radius: Unit("m")) -> Unit("Pa"): """ Compute the pressure in a body of liquid (relative to the steady-state pressure) The calculation does not include gravity. Also see https://www.youtube.com/watch?v=kIH7wEq3H-M Also see https://www.physicsforums.com/threads/pressure-of-a-rotating-bucket-of-liquid.38112/ """ density = normalize_numeric(density) speed = normalize_numeric(speed) radius = normalize_numeric(radius) return density * angular_speed(speed)**2 * radius**2
def barlow_tangential(outer_diameter: Unit("m"), inner_diameter: Unit("m"), pressure: Unit("Pa")) -> Unit("Pa"): """ Compute the tangential stress of a pressure vessel at [pressure] using Barlow's formula for thin-walled tubes. Note that this formula only applies for (outer_diameter/inner_diameter) < 1.2 ! (this assumption is not checked). Otherwise, the stress distribution will be too uneven. """ outer_diameter = normalize_numeric(outer_diameter) inner_diameter = normalize_numeric(inner_diameter) pressure = normalize_numeric(pressure) dm = (outer_diameter + inner_diameter) / 2 s = (outer_diameter - inner_diameter) / 2 return pressure * dm / (2 * s)
def serial_resistors(*args) -> Unit("Ω"): """ Compute the total resistance of n parallel resistors and return the value in Ohms. """ resistors = list(map(normalize_numeric, args)) return sum(resistors)
def capacitive_reactance(c, f=1000.0) -> Unit("Ω"): """ Compute the capacitive reactance for a given capacitance and frequency. """ c = normalize_numeric(c) f = normalize_numeric(f) return 1.0 / (2 * np.pi * f * c)
def actual_load_capacitance(cext, cpin="3 pF", cstray="2 pF") -> Unit("F"): """ Compute the actual load capacitance of a crystal given: - The external capacitance value (use "10 pF" if your have a 10 pF capacitor on each of the crystal pins) - The parasitic pin capacitance The value returned should match the load capacitance value in the crystal datasheet. Based on (C1 * C2) / (C1 + C2) + Cstray If yu use a >>> auto_format(actual_load_capacitance, "5 pF", cpin="3 pF", cstray="2pF") '6.00 pF' Parameters ---------- cext : float The load capacitor value cstray : float The stray capacitance cpin : float The capacitance of one of the oscillator pins of the connected device """ cext = normalize_numeric(cext) cstray = normalize_numeric(cstray) cpin = normalize_numeric(cpin) # cload = (C1 * C2) / (C1 + C2) + Cstray where C1 == C2 # => solve A = (B*B) / (B+B) + C for B # => solve A = ((B+P)*(B+P)) / ((B+P)+(B+P)) + C for B ctotal = cext + cpin return cstray + ((ctotal * ctotal) / (ctotal + ctotal))
def inductive_reactance(l, f=1000.0) -> Unit("Ω"): """ Compute the inductive reactance for a given inductance and frequency. """ l = normalize_numeric(l) f = normalize_numeric(f) return 2 * np.pi * f * l
def ptx_temperature(r0, r, standard=ptxITS90, poly=None) -> Unit("°C"): """ Compute the PTx temperature at a given temperature. Accepts an additive correction polynomial that is applied to the resistance. If the poly kwarg is None, the polynom is automatically selected. noCorrection is used for other r0 values. In this case, use a custom polynomial (numpy poly1d object) as the poly kwarg. See http://www.thermometricscorp.com/pt1000 for reference """ r = normalize_numeric(r) A, B = standard.a, standard.b # Select if poly is None: if abs(r0 - 1000.0) < 1e-3: poly = pt1000Correction elif abs(r0 - 100.0) < 1e-3: poly = pt100Correction else: poly = noCorrection t = ((-r0 * A + np.sqrt(r0 * r0 * A * A - 4 * r0 * B * (r0 - r))) / (2.0 * r0 * B)) # For subzero-temperature refine the computation by the correction polynomial if isinstance(r, numbers.Number): if r < r0: t += poly(r) else: # Treated like a numpy array t += poly(r) * np.piecewise(r, [r < r0, r >= r0], [1.0, 0.0]) return t
def load_capacitors(cload, cpin="3 pF", cstray="2 pF") -> Unit("F"): """ Compute the load capacitors which should be used for a given crystal, given that the load capacitors should be symmetric (i.e. have the same value). NOTE: You need to use a stray capacitance value that does NOT include the parasitic pin capacitance! Based on (C1 * C2) / (C1 + C2) + Cstray for C1 == C2 == (returned value) + cpin >>> auto_format(load_capacitors, "6 pF", cpin="3 pF", cstray="2pF") '5.00 pF' Parameters ---------- cload : float The load capacitance as given in the crystal datasheet cstray : float The stray capacitance cpin : float The capacitance of one of the oscillator pins of the connected device """ cload = normalize_numeric(cload) cstray = normalize_numeric(cstray) cpin = normalize_numeric(cpin) # cload = (C1 * C2) / (C1 + C2) + Cstray where C1 == C2 # => solve A = (B*B) / (B+B) + C for B # => solve A = ((B+P)*(B+P)) / ((B+P)+(B+P)) + C for B return (2 * (cload - cstray)) - cpin
def parallel_resistors(*args) -> Unit("Ω"): """ Compute the total resistance of n parallel resistors and return the value in Ohms. """ resistors = np.asarray(list(map(normalize_numeric, args))) return 1.0 / np.sum(np.reciprocal(resistors))
def voltage_divider_voltage(rtop, rbot, vin, rload=np.inf) -> Unit("V"): """ Compute the voltage output of a voltage divider If rload is supplied, additional load (in parallel to R2) is taken into account. """ vin = normalize_numeric(vin) return voltage_divider_ratio(rtop, rbot, rload=rload) * vin
def bottom_resistor_by_ratio(rtop, ratio) -> Unit("Ω"): """ Compute the bottom resistor of a voltage divider given the top resistor value and the division ration """ rtop = normalize_numeric(rtop) ratio = normalize_numeric(ratio) return -(rtop * ratio) / (ratio - 1.0)
def top_resistor_by_ratio(rbottom, ratio) -> Unit("Ω"): """ Compute the bottom resistor of a voltage divider given the top resistor value and the division ration """ rbottom = normalize_numeric(rbottom) ratio = normalize_numeric(ratio) return rbottom * (1.0 / ratio - 1.0)
def dBuV_to_voltage(v) -> Unit("V"): """ Represent a dB microvolt voltage in volt. Also see the online calculator at https://techoverflow.net/2019/07/28/db%c2%b5v-to-volts-online-calculator-python-code/ """ return db_field_to_ratio(v) * 1e-6
def unloaded_ratio(r1, r2) -> Unit(""): """ Compute the denominator of the division ratio of a voltage divider, not taking into account parasitic properties or loading """ r1 = normalize_numeric(r1) r2 = normalize_numeric(r2) return r2 / (r1 + r2)
def resistor_by_voltage_and_current(voltage, current) -> Unit("Ω"): """ Compute the resistance value in Ohms that draws the given amount of current if the given voltage is across it. """ voltage = normalize_numeric(voltage) current = normalize_numeric(current) return voltage / current
def current_by_power(power="25 W", voltage="230 V") -> Unit("A"): """ Given a device's power (or RMS power) and the voltage (or RMS voltage) it runs on, compute how much current it will draw. """ power = normalize_numeric(power) voltage = normalize_numeric(voltage) return power / voltage
def voltage_to_dBuV(v) -> Unit("dBµV"): """ Represent a voltage as dB microvolts. Also see the online calculator at https://techoverflow.net/2019/07/29/volts-to-db%c2%b5v-online-calculator-ampamp-python-code/ """ return value_to_db_field(v, 1e-6)
def power_by_current_and_voltage(current="1.0 A", voltage="230 V") -> Unit("W"): """ Given a device's current (or RMS current) and the voltage (or RMS current) it runs on, compute its power """ current = normalize_numeric(current) voltage = normalize_numeric(voltage) return current * voltage
def loaded_ratio(r1, r2, rl) -> Unit(""): """ Compute the denominator of the division ratio of a voltage divider, not taking into account parasitic properties but loading. """ r1 = normalize_numeric(r1) r2 = normalize_numeric(r2) rl = normalize_numeric(rl) return r1 / (r1 + parallel_resistors(r2, rl))
def voltage_divider_ratio(rtop, rbot, rload=np.inf) -> Unit(""): """ Compute the division ratio of a voltage divider. If rload is supplied, additional load (in parallel to R2) is taken into account. """ rtop = normalize_numeric(rtop) rbot = normalize_numeric(rbot) return rbot / (rtop + parallel_resistors(rbot, rload))
def capacitor_charge(capacitance, voltage) -> Unit("C"): """ Compute the total charge stored in a capacitor given: - The capacitance in farads - The voltage the capacitor is charged to The charge is returned in coulombs. """ capacitance = normalize_numeric(capacitance) voltage = normalize_numeric(voltage) return capacitance * voltage
def capacitor_energy(capacitance, voltage) -> Unit("J"): """ Compute the total energy stored in a capacitor given: - The capacitance in farads - The voltage the capacitor is charged to The energy is returned as joules. """ capacitance = normalize_numeric(capacitance) voltage = normalize_numeric(voltage) return 0.5 * capacitance * np.square(voltage)
def parallel_resistors(*args) -> Unit("Ω"): """ Compute the total resistance of n parallel resistors and return the value in Ohms. """ resistors = np.asarray(list(map(normalize_numeric, args))) # Check for zeros if len(np.nonzero(resistors)[0]) != len(resistors): return 0.0 return 1.0 / np.sum(np.reciprocal(resistors.astype(np.float)))
def johnson_nyquist_noise_voltage(r, delta_f, T) -> Unit("V"): """ Compute the Johnson Nyquist noise voltage in volts T must be given in °C whereas r must be given in Ohms. The result is given in volts """ r = normalize_numeric(r) delta_f = normalize_numeric(delta_f) t_kelvin = normalize_temperature(T) return math.sqrt(4 * boltzmann_k * t_kelvin * delta_f * r)
def temperature_with_dissipation(power_dissipated="1 W", theta="50 °C/W", t_ambient="25 °C") -> Unit("°C"): """ Compute the temperature of a component, given its thermal resistance (theta), its dissipated power and """ power_dissipated = normalize_numeric(power_dissipated) theta = normalize_numeric(theta) t_ambient = normalize_temperature_celsius(t_ambient) return t_ambient + power_dissipated * theta
def johnson_nyquist_noise_current(r, delta_f, T) -> Unit("A"): """ Compute the Johnson Nyquist noise current in amperes T must be given in °C whereas r must be given in Ohms. The result is given in volts """ r = normalize_numeric(r) delta_f = normalize_numeric(delta_f) t_kelvin = normalize_temperature(T) # Support celsius and kelvin inputs return math.sqrt((4 * boltzmann_k * t_kelvin * delta_f)/r)
def actualNoise(density, bandwith) -> Unit("V"): """ Compute the actual noise given: - A noise density in x/√Hz where x is any unit - A bandwith in ΔHz >>> autoFormat(actualNoise, "100 µV", "100 Hz") '1.00 mV' """ density = normalize_numeric(density) bandwith = normalize_numeric(bandwith) return np.sqrt(bandwith) * density
def power_to_dBm(v) -> Unit("dBµV"): """ Represent a power in Watts as dB milliwatts. """ return value_to_db_power(v, 1e-3) #def dbM_to_power(v) -> Unit("dBµV"): # """ # Represent a power in Watts as dB milliwatts. # """ # return db_power_to_ratio(v) * 1e-6
def noiseDensity(actual_noise, bandwith) -> Unit("V/√Hz"): """ Compute the noise density given: - A noise density in x/√Hz where x is any unit - A bandwith in ΔHz >>> formatValue(noiseDensity("1.0 mV", "100 Hz"), "V/√Hz") '100 μV/√Hz' """ actual_noise = normalize_numeric(actual_noise) bandwith = normalize_numeric(bandwith) return actual_noise / np.sqrt(bandwith)