예제 #1
0
	def _calculate(name, f, period, bit_width, prescaler):
		t_cnt_cycle = 1 / float(f) * prescaler
		t_full_overflow = t_cnt_cycle * (2 ** bit_width)
		cycles_ideal = round(float(period) / t_cnt_cycle)

		# However, we're limited by the counter.
		cycles = cycles_ideal
		if cycles < 1:
			cycles = 1
		elif cycles > (2 ** bit_width):
			cycles = 2 ** bit_width
		preload = (2 ** bit_width) - cycles

		actual_period = t_cnt_cycle * cycles
		error = (actual_period - float(period)) / float(period)

		return {
			"name":				name,
			"prescaler":		prescaler,
			"t_cnt_cycle":		UnitValue(t_cnt_cycle).to_dict(),
			"t_full_overflow":	UnitValue(t_full_overflow).to_dict(),
			"f_full_overflow":	UnitValue(1 / t_full_overflow).to_dict(),
			"cycles_ideal":		cycles_ideal,
			"cycles":			cycles,
			"actual_period":	UnitValue(actual_period).to_dict(),
			"actual_frequency":	UnitValue(1 / actual_period).to_dict(),
			"error":			error,
			"preload":			preload,
		}
예제 #2
0
	def request(self, endpoint, parameters):
		if parameters["f_std"] != "":
			f = UnitValue(parameters["f_std"])
		else:
			f = UnitValue(parameters["f_user"])
		ckdiv8 = "ckdiv8" in parameters
		if ckdiv8:
			f = UnitValue(f.exact_value / 8)
		period = UnitValue(parameters["period"])
		bit_width = int(parameters["bit_width"])
		if parameters["prescaler"] != "":
			user_prescaler = int(parameters["prescaler"])
		else:
			user_prescaler = None

		options = [ ]
		for prescaler_value in [ 1, 8, 64, 256, 1024 ]:
			option = self._calculate("Prescaler CK / %d" % (prescaler_value), f = f, period = period, bit_width = bit_width, prescaler = prescaler_value)
			options.append(option)
		options.sort(key = lambda opt: abs(opt["error"]))

		if user_prescaler is not None:
			option = self._calculate("User choice", f = f, period = period, bit_width = bit_width, prescaler = user_prescaler)
			options.insert(0, option)

		return {
			"options": options,
		}
예제 #3
0
	def test_init_unitvalue(self):
		x = UnitValue("1.2345")
		self.assertEqual(x, x)

		y = UnitValue("1.2345")
		self.assertEqual(x, y)

		y = UnitValue(x)
		self.assertEqual(x, y)
예제 #4
0
	def test_str_units(self):
		self.assertAlmostEqual(float(UnitValue("12345f")), 12345e-15)
		self.assertAlmostEqual(float(UnitValue("12345p")), 12345e-12)
		self.assertAlmostEqual(float(UnitValue("12345n")), 12345e-9)
		self.assertAlmostEqual(float(UnitValue("12345u")), 12345e-6)
		self.assertAlmostEqual(float(UnitValue("12345m")), 12345e-3)
		self.assertAlmostEqual(float(UnitValue("12345")), 12345)
		self.assertAlmostEqual(float(UnitValue("12345k")), 12345e3)
		self.assertAlmostEqual(float(UnitValue("12345M")), 12345e6)
		self.assertAlmostEqual(float(UnitValue("12345G")), 12345e9)
		self.assertAlmostEqual(float(UnitValue("12345T")), 12345e12)
예제 #5
0
    def from_dict(cls, dict_data):
        if not "name" in dict_data:
            raise DataMissingException(
                "No 'name' attribute in ValueSet definition: %s" %
                (str(dict_data)))
        if not "type" in dict_data:
            raise DataMissingException(
                "No 'type' attribute in ValueSet definition: %s" %
                (str(dict_data)))

        vs_type = dict_data["type"]
        if vs_type == "explicit":
            if not "items" in dict_data:
                raise DataMissingException(
                    "No 'items' attribute in explicit ValueSet definition: %s"
                    % (str(dict_data)))
            return cls(name=dict_data["name"],
                       values=[UnitValue(v) for v in dict_data["items"]])
        elif vs_type == "eseries":
            if not "series" in dict_data:
                raise DataMissingException(
                    "No 'series' attribute in eseries ValueSet definition: %s"
                    % (str(dict_data)))
            if not "min" in dict_data:
                raise DataMissingException(
                    "No 'min' attribute in eseries ValueSet definition: %s" %
                    (str(dict_data)))
            if not "max" in dict_data:
                raise DataMissingException(
                    "No 'max' attribute in eseries ValueSet definition: %s" %
                    (str(dict_data)))

            eseries = ESeries.standard(dict_data["series"])
            (minval,
             maxval) = UnitValue(dict_data["min"]), UnitValue(dict_data["max"])
            values = [
                UnitValue(v) for v in eseries.from_to(minval.exact_value,
                                                      maxval.exact_value,
                                                      maxvalue_inclusive=True)
            ]
            return cls(name=dict_data["name"], values=values)
        elif vs_type == "union":
            if not "groups" in dict_data:
                raise DataMissingException(
                    "No 'groups' attribute in union ValueSet definition: %s" %
                    (str(dict_data)))
            return cls(name=dict_data["name"],
                       values=None,
                       additional_data=dict_data["groups"])
        else:
            raise InvalidDataException(
                "Invalid 'type' attribute of ValueSet '%s': %s" %
                (vs_type, str(dict_data)))
예제 #6
0
	def _calculate_choice(name, r, v_in, v_load, i):
		r_load = v_load / i
		actual_v_load = v_in * r_load / (r_load + float(r))
		rel_error = (actual_v_load - v_load) / v_load
		abs_error = UnitValue(actual_v_load - v_load)
		return {
			"name":			name,
			"r":			UnitValue(r).to_dict(),
			"v_load":		UnitValue(actual_v_load).to_dict(),
			"rel_error":	rel_error,
			"abs_error":	abs_error.to_dict(),
		}
예제 #7
0
 def request(self, endpoint, parameters):
     value = UnitValue(parameters["input_value"])
     significant_digits = int(parameters["significant_digits"])
     return {
         "value": value.to_dict(significant_digits=significant_digits),
         "significant_digits": significant_digits,
     }
예제 #8
0
    def request(self, endpoint, parameters):
        v_in = UnitValue(parameters["v_in"])
        v_out = UnitValue(parameters["v_out"])
        r_sum = UnitValue(parameters["r_sum"])
        r_set = self.config.get_valuesets("r")[parameters["r_set"]]
        r_tolerance = float(parameters["r_tolerance"]) / 100

        options = []
        ideal_r1 = float(r_sum) * (float(v_out)) / float(v_in)
        min_r1 = ideal_r1 * (1 - r_tolerance)
        max_r1 = ideal_r1 * (1 + r_tolerance)
        for r1 in r_set.iter_range(min_r1, max_r1):
            ideal_r2 = float(r1) * (float(v_in) - float(v_out)) / float(v_out)
            for r2 in r_set.iter_closest(ideal_r2):
                opt_v_out = float(v_in) * float(r1) / (float(r1) + float(r2))
                opt_r_sum = float(r1) + float(r2)
                opt_i = float(v_in) / opt_r_sum
                opt_p = (opt_i**2) * opt_r_sum
                option = {
                    "r1": r1.to_dict(),
                    "r2": r2.to_dict(),
                    "r_total": UnitValue(opt_r_sum).to_dict(),
                    "v_out": UnitValue(opt_v_out).to_dict(),
                    "v_error": (opt_v_out - float(v_out)) / float(v_out),
                    "r_error": (opt_r_sum - float(r_sum)) / float(r_sum),
                    "i": UnitValue(opt_i).to_dict(),
                    "p": UnitValue(opt_p).to_dict(),
                }
                options.append(option)
        options.sort(
            key=lambda opt: (abs(opt["v_error"]), abs(opt["r_error"])))

        return {
            "options": options,
        }
예제 #9
0
 def to_dict(self, repr_callback=None):
     return {
         "name":
         self.name,
         "values": [
             UnitValue(element, repr_callback=repr_callback).to_dict()
             for element in self._values
         ],
     }
예제 #10
0
 def find_closest(self, value):
     value = UnitValue(value)
     index = bisect.bisect(self._values, value) - 1
     if index >= 0:
         smaller = self._values[index]
     else:
         smaller = None
     if index + 1 < len(self._values):
         larger = self._values[index + 1]
     else:
         larger = None
     return (smaller, larger)
예제 #11
0
    def request(self, endpoint, parameters):
        if parameters["f_std"] != "":
            f = UnitValue(parameters["f_std"])
        else:
            f = UnitValue(parameters["f_user"])
        ckdiv8 = "ckdiv8" in parameters
        u2x = "u2x" in parameters
        if ckdiv8:
            f = UnitValue(f.exact_value / 8)
        ckdivisor = 8 if u2x else 16

        result_items = []
        for baudrate in self.config.get_valuesets(
                "baudrate")["Standard"].values.ordered_tuple:
            ubrr = max(0, round(float(f) / (ckdivisor * float(baudrate))) - 1)
            act_baudrate = float(f) / (ckdivisor * (ubrr + 1))
            error = (act_baudrate - float(baudrate)) / float(baudrate)
            ideal_freq = float(baudrate) * (ckdivisor * (ubrr + 1))
            if ckdiv8:
                ideal_freq *= 8

            result_items.append({
                "baudrate":
                baudrate.to_dict(include_repr=True),
                "act_baudrate":
                act_baudrate,
                "ubrr":
                ubrr,
                "error":
                error,
                "ideal_freq":
                UnitValue(
                    ideal_freq,
                    repr_callback=lambda value: value.format(
                        significant_digits=6)).to_dict(include_repr=True),
            })

        return {
            "items": result_items,
        }
예제 #12
0
    def request(self, endpoint, parameters):
        marking = parameters["marking"].strip()
        try:
            int_marking = int(marking)
        except ValueError:
            int_marking = None
        try:
            flt_marking = float(marking)
        except ValueError:
            flt_marking = None

        if (int_marking is not None) and (int_marking >= 100):
            (base, exponent) = divmod(int_marking, 10)
            value = base * (10**exponent)
            (r, c, l) = (1, 1e-12, 1e-6)
        elif flt_marking is not None:
            value = flt_marking
            (r, c, l) = (1, 1e-12, None)
        else:
            replacers = {
                "r": (1, None, 1e-6),
                "u": (None, 1e-6, 1e-6),
                "n": (None, 1e-9, 1e-9),
                "p": (None, 1e-12, None),
            }
            lmarking = marking.lower()
            for (character, (r, c, l)) in replacers.items():
                if character in lmarking:
                    value = float(lmarking.replace(character, "."))
                    break
            else:
                raise InputDataException("Unable to interpret \"%s\"." %
                                         (marking))
        return {
            "r": UnitValue(value * r).to_dict() if r else None,
            "c": UnitValue(value * c).to_dict() if c else None,
            "l": UnitValue(value * l).to_dict() if l else None,
        }
예제 #13
0
    def request(self, endpoint, parameters):
        f_in = UnitValue(parameters["f_in"])
        f_out = UnitValue(parameters["f_out"])
        multipliers = self._parse_ckfield(parameters["mul"])
        dividers = SortedList(self._parse_ckfield(parameters["div"]))

        results = []
        ratio = float(f_out) / float(f_in)
        for multiplier in multipliers:
            ideal_divider = multiplier / ratio
            for divider in dividers.less_more_list(ideal_divider):
                f_result = float(f_in) * multiplier / divider
                error = (f_result - float(f_out)) / float(f_out)

                result = {
                    "multiplier": multiplier,
                    "divider": divider,
                    "f_out": UnitValue(f_result).to_dict(),
                    "error": error,
                }
                results.append(result)
        results.sort(key=lambda result: abs(result["error"]))

        return results
예제 #14
0
    def request(self, endpoint, parameters):
        r = UnitValue(parameters["r"])
        r_set = self.config.get_valuesets("r")[parameters["r_set"]]

        options = []
        for r1 in r_set:
            if r1 == r:
                continue
            ideal_r2 = 1 / ((1 / float(r)) - (1 / float(r1)))
            for r2 in r_set.iter_closest(ideal_r2):
                if r2 < r1:
                    continue
                r_total = 1 / ((1 / float(r1)) + (1 / float(r2)))
                error = (r_total - float(r)) / float(r)
                if abs(error) > 0.75:
                    continue
                option = {
                    "r1":
                    UnitValue(r1).to_dict(),
                    "r2":
                    UnitValue(r2).to_dict(),
                    "r":
                    UnitValue(
                        r_total,
                        repr_callback=lambda v: v.format(
                            significant_digits=4)).to_dict(include_repr=True),
                    "error":
                    error,
                    "ratio":
                    float(r2) / float(r1),
                }
                options.append(option)
        options.sort(key=lambda o: (abs(o["error"]), o["ratio"]))
        return {
            "options": options[:15],
        }
예제 #15
0
    def request(self, endpoint, parameters):
        if parameters["v"].strip() == "":
            i = UnitValue(parameters["i"])
            r = UnitValue(parameters["r"])
            v = UnitValue(float(i) * float(r))
        elif parameters["i"].strip() == "":
            r = UnitValue(parameters["r"])
            v = UnitValue(parameters["v"])
            i = UnitValue(float(v) / float(r))
        elif parameters["r"].strip() == "":
            v = UnitValue(parameters["v"])
            i = UnitValue(parameters["i"])
            r = UnitValue(float(v) / float(i))
        else:
            raise InputDataException(
                "Exactly one of V, I, R must be left empty.")
        p = UnitValue((float(i)**2) * float(r))

        return {
            "v": v.to_dict(),
            "i": i.to_dict(),
            "r": r.to_dict(),
            "p": p.to_dict(),
        }
예제 #16
0
	def request(self, endpoint, parameters):
		v_in = UnitValue(parameters["v_in"])
		v_load = UnitValue(parameters["v_load"])
		i = UnitValue(parameters["i"])

		if v_in < v_load:
			raise InputDataException("Input voltage is lower than load voltage.")

		v_r = float(v_in) - float(v_load)
		r = v_r / float(i)
		p_r = float(i) * v_r
		p_load = float(i) * float(v_load)
		eta = float(v_load) / float(v_in)

		choices = [ ]
		if parameters["r_user"] != "":
			r_user = UnitValue(parameters["r_user"])
			choices.append(self._calculate_choice("User choice", r = r_user, v_in = float(v_in), v_load = float(v_load), i = float(i)))

		if parameters["r_set"] != "":
			r_set = self.config.get_valuesets("r")[parameters["r_set"]]
			(smaller, larger) = r_set.find_closest(r)
			if smaller is not None:
				choices.append(self._calculate_choice("Smaller in set", r = smaller, v_in = float(v_in), v_load = float(v_load), i = float(i)))
			if larger is not None:
				choices.append(self._calculate_choice("Larger in set", r = larger, v_in = float(v_in), v_load = float(v_load), i = float(i)))

		return {
			"v_in":		v_in.to_dict(),
			"v_load":	v_load.to_dict(),
			"i":		i.to_dict(),
			"v_r":		UnitValue(v_r).to_dict(),
			"r":		UnitValue(r).to_dict(),
			"p_r":		UnitValue(p_r).to_dict(),
			"p_load":	UnitValue(p_load).to_dict(),
			"p_total":	UnitValue(p_r + p_load).to_dict(),
			"eta":		eta,
			"choices":	choices,
		}
예제 #17
0
	def request(self, endpoint, parameters):
		r1 = UnitValue(parameters["r1"])
		r2 = UnitValue(parameters["r2"])
		c1 = UnitValue(parameters["c1"])

		t_on = 0.693 * (float(r1) + float(r2)) * float(c1)
		t_off = 0.693 * float(r2) * float(c1)
		t = t_on + t_off
		f = 1 / t
		duty = t_on / t

		return {
			"r1":			r1.to_dict(),
			"r2":			r2.to_dict(),
			"c1":			c1.to_dict(),
			"t":			UnitValue(t).to_dict(),
			"t_on":			UnitValue(t_on).to_dict(),
			"t_off":		UnitValue(t_off).to_dict(),
			"f":			UnitValue(f).to_dict(),
			"duty":			duty,
		}
예제 #18
0
    def request(self, endpoint, parameters):
        diameter = UnitValue(parameters["diameter"])
        length = UnitValue(parameters["length"])
        turns = int(parameters["turns"])
        pitch = float(length) / turns
        diameter_inch = UnitValue(diameter.exact_value * 10000 / 254)

        reference = Thread(diameter=float(diameter), pitch=pitch)
        candidates = list(self.config.thread_db.closest(reference))
        candidates = [{
            "group":
            candidate.group,
            "name":
            candidate.name,
            "usage":
            candidate.usage,
            "diameter":
            UnitValue(candidate.diameter).to_dict(),
            "diameter_frac":
            FractionalRepresentation(candidate.diameter * 10000 / 254,
                                     max_abs_fractional_error=0.01).to_dict(),
            "pitch":
            UnitValue(candidate.pitch).to_dict(),
            "pitch_tpi":
            candidate.pitch_tpi,
            "diameter_err":
            (candidate.diameter - float(diameter)) / float(diameter),
            "pitch_err": (candidate.pitch - pitch) / pitch,
        } for candidate in candidates]

        return {
            "diameter":
            diameter.to_dict(),
            "diameter_inch":
            diameter_inch.to_dict(),
            "diameter_frac":
            FractionalRepresentation(diameter_inch.exact_value,
                                     max_abs_fractional_error=0.01).to_dict(),
            "pitch":
            UnitValue(pitch).to_dict(),
            "pitch_tpi":
            0.0254 / pitch,
            "candidates":
            candidates,
        }
예제 #19
0
    def request(self, endpoint, parameters):
        v_out = UnitValue(parameters["v_out"])
        r_set = self.config.get_valuesets("r")[parameters["r_set"]]
        l = UnitValue(parameters["l"]) if (parameters["l"] != "") else None
        v_in = UnitValue(
            parameters["v_in"]) if (parameters["v_in"] != "") else None
        i_out = UnitValue(
            parameters["i_out"]) if (parameters["i_out"] != "") else None
        f = 325e3

        options = []
        for r2 in r_set.iter_range(500, 50000):
            ideal_r1 = (float(v_out) / 0.925 * float(r2)) - float(r2)
            for r1 in r_set.iter_closest(ideal_r1):
                actual_v_out = 0.925 * (float(r1) + float(r2)) / float(r2)
                error = (actual_v_out - float(v_out)) / float(v_out)
                option = {
                    "r1": r1.to_dict(),
                    "r2": r2.to_dict(),
                    "v_out": UnitValue(actual_v_out).to_dict(),
                    "error": error,
                }
                if (v_in is not None) and (l is not None):
                    # Inductor and V_IN also given, calculate Delta I_L
                    option["delta_i_load"] = UnitValue(
                        ((float(v_in) * float(v_out)) - (float(v_out)**2)) /
                        (f * float(l) * float(v_in))).to_dict()
                if (v_in is not None) and (l is not None) and (i_out
                                                               is not None):
                    option["max_inductor_i"] = UnitValue(
                        float(i_out) +
                        (float(v_out) / (2 * f * float(l)) *
                         (1 - (float(v_out) / float(v_in))))).to_dict()
                options.append(option)
        options.sort(key=lambda opt: abs(opt["error"]))
        return {
            "show_other": (v_in is not None) and (l is not None),
            "options": options[:15],
        }
예제 #20
0
	def test_format_units(self):
		self.assertEqual(UnitValue(1.23e-17).format(significant_digits = 3), "0.0123 f")
		self.assertEqual(UnitValue(1.23e-16).format(significant_digits = 3), "0.123 f")
		self.assertEqual(UnitValue(1.23e-15).format(significant_digits = 3), "1.23 f")
		self.assertEqual(UnitValue(1.23e-14).format(significant_digits = 3), "12.3 f")
		self.assertEqual(UnitValue(1.23e-13).format(significant_digits = 3), "123 f")
		self.assertEqual(UnitValue(1.23e-12).format(significant_digits = 3), "1.23 p")
		self.assertEqual(UnitValue(1.23e-11).format(significant_digits = 3), "12.3 p")
		self.assertEqual(UnitValue(1.23e-10).format(significant_digits = 3), "123 p")
		self.assertEqual(UnitValue(1.23e-9).format(significant_digits = 3), "1.23 n")
		self.assertEqual(UnitValue(1.23e-8).format(significant_digits = 3), "12.3 n")
		self.assertEqual(UnitValue(1.23e-7).format(significant_digits = 3), "123 n")
		self.assertEqual(UnitValue(1.23e-6).format(significant_digits = 3), "1.23 µ")
		self.assertEqual(UnitValue(1.23e-5).format(significant_digits = 3), "12.3 µ")
		self.assertEqual(UnitValue(1.23e-4).format(significant_digits = 3), "123 µ")
		self.assertEqual(UnitValue(1.23e-3).format(significant_digits = 3), "1.23 m")
		self.assertEqual(UnitValue(1.23e-2).format(significant_digits = 3), "12.3 m")
		self.assertEqual(UnitValue(1.23e-1).format(significant_digits = 3), "123 m")
		self.assertEqual(UnitValue(1.23e0).format(significant_digits = 3), "1.23 ")
		self.assertEqual(UnitValue(1.23e1).format(significant_digits = 3), "12.3 ")
		self.assertEqual(UnitValue(1.23e2).format(significant_digits = 3), "123 ")
		self.assertEqual(UnitValue(1.23e3).format(significant_digits = 3), "1.23 k")
		self.assertEqual(UnitValue(1.23e4).format(significant_digits = 3), "12.3 k")
		self.assertEqual(UnitValue(1.23e5).format(significant_digits = 3), "123 k")
		self.assertEqual(UnitValue(1.23e6).format(significant_digits = 3), "1.23 M")
		self.assertEqual(UnitValue(1.23e7).format(significant_digits = 3), "12.3 M")
		self.assertEqual(UnitValue(1.23e8).format(significant_digits = 3), "123 M")
		self.assertEqual(UnitValue(1.23e9).format(significant_digits = 3), "1.23 G")
		self.assertEqual(UnitValue(1.23e10).format(significant_digits = 3), "12.3 G")
		self.assertEqual(UnitValue(1.23e11).format(significant_digits = 3), "123 G")
		self.assertEqual(UnitValue(1.23e12).format(significant_digits = 3), "1.23 T")
		self.assertEqual(UnitValue(1.23e13).format(significant_digits = 3), "12.3 T")
		self.assertEqual(UnitValue(1.23e14).format(significant_digits = 3), "123 T")
		self.assertEqual(UnitValue(1.23e15).format(significant_digits = 3), "1.23 E")
		self.assertEqual(UnitValue(1.23e16).format(significant_digits = 3), "12.3 E")
		self.assertEqual(UnitValue(1.23e17).format(significant_digits = 3), "123 E")
		self.assertEqual(UnitValue(1.23e18).format(significant_digits = 3), "1230 E")
		self.assertEqual(UnitValue(1.23e19).format(significant_digits = 3), "12300 E")
예제 #21
0
	def test_reformat_1u(self):
		value = UnitValue("1u")
		self.assertEqual(value.format(significant_digits = 3), "1.00 µ")
예제 #22
0
    def request(self, endpoint, parameters):
        t1 = UnitValue(parameters["t1"])
        v1 = UnitValue(parameters["v1"])
        t2 = UnitValue(parameters["t2"])
        v2 = UnitValue(parameters["v2"])
        if t1 > t2:
            (t1, v1, t2, v2) = (t2, v2, t1, v1)

        if v2 < v1:
            # Capacitor is discharging
            # v(t) = v0 * exp(-t / tau)
            # v1 = v0 * exp(-t1 / tau)  ->  v0 = v1 / exp(-t1 / tau)
            # v2 = v0 * exp(-t2 / tau)  ->  v0 = v2 / exp(-t2 / tau)
            # v1 / exp(-t1 / tau) = v2 / exp(-t2 / tau)
            # v1 / v2 = exp(-t1 / tau) / exp(-t2 / tau) = exp((-t1 - (-t2)) / tau) = exp((t2 - t1) / tau)
            # (t2 - t1) / tau = ln(v1 / v2)
            # tau = (t2 - t1) / ln(v1 / v2)
            tau = (float(t2) - float(t1)) / math.log(float(v1) / float(v2))
            v0 = float(v1) / math.exp(-float(t1) / tau)
        else:
            # Capacitor is charging, here we need to rely on numeric solution.
            # v(t) = v0 * (1 - exp(-t / tau))
            # v1 = v0 * exp(-t1 / tau)
            # v2 = v0 * exp(-t2 / tau)
            # v1 / v2 = exp(-t1 / tau) / exp(-t2 / tau)
            # Substitute: d = v1 / v2
            # d = exp(-t1 / tau) / exp(-t2 / tau)
            # d - exp(-t1 / tau) / exp(-t2 / tau) = 0
            # Solve this by Newton's method.
            d = float(v1) / float(v2)
            function = _ChargingCapFunction(d=float(v1) / float(v2),
                                            t1=float(t1),
                                            t2=float(t2))
            try:
                tau = NewtonSolver(function).solve(x0=1)
                v0 = float(v1) / (1 - math.exp(-float(t1) / tau))
            except ZeroDivisionError:
                raise InputDataException(
                    "Result is numerically instable, cannot solve.")

        if tau < 0:
            raise InputDataException(
                "Result is numerically instable, tau was negative.")

        # Now, plausibilize values.
        if v2 < v1:
            calc_v1 = v0 * math.exp(-float(t1) / tau)
            calc_v2 = v0 * math.exp(-float(t2) / tau)
        else:
            calc_v1 = v0 * (1 - math.exp(-float(t1) / tau))
            calc_v2 = v0 * (1 - math.exp(-float(t2) / tau))

        error_v1 = abs(calc_v1 - float(v1))
        error_v2 = abs(calc_v2 - float(v2))
        max_error = max(error_v1, error_v2)
        if (max_error > 1e-3):
            raise InputDataException(
                "Result is numerically instable and diverged. Refusing to give a completely wrong answer. Absolute error was %.2e"
                % (max_error))

        # Cutoff frequency
        f = 1 / (2 * math.pi * tau)

        return {
            "tau": tau,
            "v0": UnitValue(v0).to_dict(),
            "f": UnitValue(f).to_dict(),
        }
예제 #23
0
	def test_str_init(self):
		self.assertAlmostEqual(float(UnitValue("1.23456")), 1.23456)
		self.assertAlmostEqual(float(UnitValue(".23456")), .23456)
		self.assertAlmostEqual(float(UnitValue("0000.23456")), .23456)
예제 #24
0
 def iter_range(self, min_value, max_value):
     min_index = bisect.bisect(self._values, UnitValue(min_value)) - 1
     max_index = bisect.bisect(self._values, UnitValue(max_value))
     for index in range(min_index, max_index + 1):
         if 0 <= index < len(self._values):
             yield self._values[index]
예제 #25
0
    def request(self, endpoint, parameters):
        if parameters.get("i", "") != "":
            i = UnitValue(parameters["i"])
        else:
            i = None
        if parameters.get("thickness", "") != "":
            thickness = UnitValue(parameters["thickness"])
            thickness_unit = parameters["thickness_unit"]
            uc = UnitConversion.lengths()
            uc.add(1, "oz", 35, "um")
            thickness_mil = uc.convert(float(thickness), thickness_unit, "mil")
        else:
            thickness_mil = None
        if parameters.get("tempdelta", "") != "":
            tempdelta = UnitValue(parameters["tempdelta"])
            tempdelta_unit = parameters["tempdelta_unit"]
            uc = UnitConversion.temperatures()
            t = uc.convert_delta(float(tempdelta), tempdelta_unit, "K")
        else:
            t = None
        if parameters.get("trace_width", "") != "":
            trace_width = UnitValue(parameters["trace_width"])
            trace_width_unit = parameters["trace_width_unit"]
            uc = UnitConversion.lengths()
            trace_width_mil = uc.convert(float(trace_width), trace_width_unit,
                                         "mil")
        else:
            trace_width_mil = None
        inner_layer = (int(parameters.get("inner_layer", "0")) == 1)
        if parameters.get("trace_length", "") != "":
            trace_length = UnitValue(parameters["trace_length"])
        else:
            trace_length = None
        k = 0.024 if inner_layer else 0.048

        # IPC-2221A, pg. 50
        # k = 0.048 for outer, 0.024 for inner layers
        # I = k * T^0.44 * A^0.725
        # A = Cross section in mil²
        # T = Temperature delta in °C
        # A = (I / k / T^0.44)^(1 / 0.725)
        # T = (I / k / A^0.725)^ (1 / 0.44)

        def unit_temperature(tempdelta_kelvin):
            return {
                "kelvin": tempdelta_kelvin,
            }

        def unit_length_mil(length_mil):
            return {
                "mil": length_mil,
            }

        def unit_area_sqrmil(area_sqrmil):
            return {
                "sqrmil": area_sqrmil,
                "mm2": area_sqrmil / ((1000 / 25.4)**2),
            }

        def unit_copper_thickness(length_mil):
            uc = UnitConversion.lengths()
            uc.add(1, "oz", 35, "um")
            return {
                "mil": length_mil,
                "oz": uc.convert(length_mil, "mil", "oz"),
                "mm": uc.convert(length_mil, "mil", "mm"),
            }

        results = []
        if (i is not None) and (t is not None) and (thickness_mil is not None):
            # Calculate trace width
            calc_A_sqrmil = (float(i) / k / (t**0.44))**(1 / 0.725)
            calc_trace_width_mil = calc_A_sqrmil / thickness_mil
            result = {
                "given": {
                    "i": i.to_dict(),
                    "t": unit_temperature(t),
                    "thickness": unit_copper_thickness(thickness_mil),
                },
                "calculated": {
                    "A": unit_area_sqrmil(calc_A_sqrmil),
                    "width": unit_length_mil(calc_trace_width_mil),
                },
            }
            results.append(result)

        if (trace_width_mil is not None) and (t is not None) and (thickness_mil
                                                                  is not None):
            # Calculate current
            calc_A_sqrmil = trace_width_mil * thickness_mil
            calc_i = UnitValue(k * (t**0.44) * (calc_A_sqrmil**0.725))

            result = {
                "given": {
                    "width": unit_length_mil(calc_trace_width_mil),
                    "t": unit_temperature(t),
                    "thickness": unit_copper_thickness(thickness_mil),
                },
                "calculated": {
                    "A": unit_area_sqrmil(calc_A_sqrmil),
                    "i": calc_i.to_dict(),
                },
            }
            results.append(result)

        if (trace_width_mil is not None) and (t is not None) and (i
                                                                  is not None):
            # Calculate copper thickness
            calc_A_sqrmil = (float(i) / k / (t**0.44))**(1 / 0.725)
            calc_copper_height_mil = calc_A_sqrmil / trace_width_mil

            result = {
                "given": {
                    "i": i.to_dict(),
                    "t": unit_temperature(t),
                    "width": unit_length_mil(trace_width_mil),
                },
                "calculated": {
                    "A": unit_area_sqrmil(calc_A_sqrmil),
                    "thickness": unit_copper_thickness(calc_copper_height_mil),
                },
            }
            results.append(result)

        if (trace_width_mil is not None) and (i is not None) and (thickness_mil
                                                                  is not None):
            # Calculate temperature rise
            calc_A_sqrmil = trace_width_mil * thickness_mil
            calc_t = (float(i) / k / (calc_A_sqrmil**0.725))**(1 / 0.44)

            result = {
                "given": {
                    "i": i.to_dict(),
                    "width": unit_length_mil(trace_width_mil),
                    "thickness": unit_copper_thickness(thickness_mil),
                },
                "calculated": {
                    "A": unit_area_sqrmil(calc_A_sqrmil),
                    "t": unit_temperature(calc_t),
                },
            }
            results.append(result)

        for result in results:
            cu_resistivity = 1.68e-8  # Ohm-meters
            area_sqrm = result["calculated"]["A"]["mm2"] / 1e6
            resistance_per_meter = cu_resistivity / area_sqrm
            result["calculated"]["R_per_cm"] = UnitValue(resistance_per_meter /
                                                         100).to_dict()
            if trace_length is not None:
                result["given"]["l"] = trace_length.to_dict()
                result["calculated"]["R"] = UnitValue(
                    resistance_per_meter * float(trace_length)).to_dict()
                if ("i" in result["given"]):
                    i = result["given"]["i"]["flt"]
                else:
                    i = result["calculated"]["i"]["flt"]
                P = (i**2) * result["calculated"]["R"]["flt"]
                result["calculated"]["P"] = UnitValue(P).to_dict()

        return results
예제 #26
0
	def test_format(self):
		self.assertEqual(UnitValue("0").format(significant_digits = 1), "0 ")
		self.assertEqual(UnitValue("0").format(significant_digits = 2), "0.0 ")
		self.assertEqual(UnitValue("0").format(significant_digits = 3), "0.00 ")
		self.assertEqual(UnitValue("0").format(significant_digits = 4), "0.000 ")

		self.assertEqual(UnitValue("1").format(significant_digits = 1), "1 ")
		self.assertEqual(UnitValue("1").format(significant_digits = 2), "1.0 ")
		self.assertEqual(UnitValue("1").format(significant_digits = 3), "1.00 ")
		self.assertEqual(UnitValue("1").format(significant_digits = 4), "1.000 ")

		self.assertEqual(UnitValue("-1").format(significant_digits = 1), "-1 ")
		self.assertEqual(UnitValue("-1").format(significant_digits = 2), "-1.0 ")
		self.assertEqual(UnitValue("-1").format(significant_digits = 3), "-1.00 ")
		self.assertEqual(UnitValue("-1").format(significant_digits = 4), "-1.000 ")

		self.assertEqual(UnitValue("1").format(significant_digits = 3), "1.00 ")
		self.assertEqual(UnitValue("12").format(significant_digits = 3), "12.0 ")
		self.assertEqual(UnitValue("123").format(significant_digits = 3), "123 ")

		self.assertEqual(UnitValue("1").format(significant_digits = 4), "1.000 ")
		self.assertEqual(UnitValue("12").format(significant_digits = 4), "12.00 ")
		self.assertEqual(UnitValue("123").format(significant_digits = 4), "123.0 ")

		self.assertEqual(UnitValue("1234").format(significant_digits = 4), "1.234 k")
		self.assertEqual(UnitValue("12345").format(significant_digits = 4), "12.35 k")
		self.assertEqual(UnitValue("123456").format(significant_digits = 4), "123.5 k")
		self.assertEqual(UnitValue("123456").format(significant_digits = 5), "123.46 k")