فهرست مقاله
یک محاسبهٔ توان میتواند از نظر اجرای پایتون درست باشد، ولی بهخاطر قرارداد دامنه یا زاویه، پاسخ مهندسی غلطی بدهد. سه خطای رایج، مخلوطکردن RMS با قله، جایگزینی ولتاژ خط بهجای فاز و فراموشکردن مزدوج جریاناند. در این درس، معیار پذیرش یک تابع توان سهفاز را با عددهای ساختگی و جواب دستی میسازیم. هیچ سیمکشی، منبع برق، بار واقعی یا ابزار اندازهگیری در آزمایش حضور ندارد.
۱. قرارداد محدودِ سهفاز ستارهٔ متعادل

سه ولتاژ و جریان، سینوسیِ همفرکانس در حالت ماندگار و با ترتیب مثبت abc فرض شدهاند. زاویههای ولتاژ نسبت به مرجع مشترک، صفر، منفی ۱۲۰ و مثبت ۱۲۰ درجهاند. بار ستاره و متعادل است؛ اندازهٔ هر سه جریان یکسان و اختلاف زاویهٔ جریان با ولتاژِ همان فاز ثابت است. این تابع مجموعهٔ نامتعادلِ دلخواهی دریافت نمیکند؛ خودش مجموعهٔ محدودِ متعادل را میسازد.
جریان از منبع به بار و وارد پایانهٔ مثبت ولتاژ بار تعریف میشود. lag را زاویهٔ ولتاژ منهای زاویهٔ جریان میگیریم؛ lag مثبت یعنی جریان پسفاز و Q مثبت. مقدار منفی برای جریان پیشفاز، Q منفی میدهد. در API، lag بین منفی ۹۰ تا مثبت ۹۰ درجه محدود است؛ بنابراین حالت بازتولید توان اکتیو به منبع، موضوع این قرارداد نیست.
فصل شبکههای چندفاز MIT ساختار متعادل و رابطهٔ ولتاژهای خط و فاز را توضیح میدهد. اینجا فقط همان دامنهٔ ساده را برای آزمون نرمافزار انتخاب کردهایم. اتصال مثلث، جابهجایی نقطهٔ ستاره در عدم تعادل، هارمونیک، گذرا و ضریب توان اعوجاجی پیادهسازی نشدهاند؛ نتیجه را به آنها تعمیم نمیدهیم.
۲. RMS و ولتاژ خط، پیش از فرمول توان

اندازهٔ ورودی v_phase_rms بر حسب ولت RMS فاز به خنثی است. i_line_rms بر حسب آمپر RMS خط است که در همین اتصال ستاره، با جریان فاز برابر است. برای ترتیب abc تعریفشده، Vab از Va منهای Vb ساخته میشود؛ اندازهاش رادیکال سه برابر اندازهٔ فاز و زاویهاش سی درجه جلوتر از Va است. تفاضل دو عدد مختلط را با تفاضل دو اندازه اشتباه نمیگیریم.
در نمونهٔ ما، ولتاژ فاز ۱۲۰ ولت است و ولتاژ خط تقریباً ۲۰۷٫۸۴۶ ولت میشود. رابطهٔ اندازهٔ توان ظاهری، هم ۳VpIp و هم رادیکال سه ضربدر VLIL است. زاویهٔ مورد استفاده در توان، اختلاف ولتاژ و جریان همان فاز است؛ اختلافِ خام زاویهٔ Vab و Ia سی درجهٔ اضافی دارد. نوشتن فرمول درست با تعریف زاویهٔ غلط همچنان پاسخ غلط میسازد.
فصل توان AC و بخش دامنهٔ RMS در MIT تفاوت قله و RMS را روشن میکند. برای فازورِ قله، حاصلضرب ولتاژ و مزدوج جریان ضریب یکدوم دارد؛ با RMS سینوسی این ضریب حذف میشود. برچسب amplitude در کد باید RMS باشد، اما برنامه نمیتواند بفهمد کاربر عدد قله را اشتباهاً با این برچسب وارد کرده است.
۳. کد کامل توان مختلط و کنترل ورودی

کد با Python 3.14.5 و کتابخانهٔ استاندارد اجرا شده است. زاویهٔ ورودی درجه است، ولی طبق مرجع cmath پایتون، rect و phase با رادیان کار میکنند؛ تبدیل را صریح انجام میدهیم. مرجع مشترک نیز در بازهٔ منفی ۱۸۰ تا مثبت ۱۸۰ درجه محدود شده تا دامنهٔ آموزشیِ ورودی روشن بماند؛ این محدودیت، قانون فیزیکی فازور نیست.
"""Original balanced positive-sequence RMS star-load power tests; no hardware."""
import cmath
from fractions import Fraction
import json
import math
import platform
def _real(value, name):
if type(value) not in (int, float):
raise TypeError(name + ' must be exact int or float')
try:
result = float(value)
except OverflowError as error:
raise ValueError(name + ' cannot be represented') from error
if not math.isfinite(result):
raise ValueError(name + ' must be finite')
return result
def balanced_star(v_phase_rms, i_line_rms, lag_degrees, reference_degrees=0,
voltage_unit='V', current_unit='A', angle_unit='deg', amplitude='RMS', connection='Y'):
"""Cosine-reference abc phases; load current enters positive voltage terminal."""
if (voltage_unit, current_unit, angle_unit, amplitude, connection) != ('V', 'A', 'deg', 'RMS', 'Y'):
raise ValueError('explicit V/A/deg/RMS/Y contract required')
vp, il, lag, reference = (_real(value, name) for value, name in (
(v_phase_rms, 'v_phase_rms'), (i_line_rms, 'i_line_rms'),
(lag_degrees, 'lag_degrees'), (reference_degrees, 'reference_degrees')))
if vp <= 0 or il < 0:
raise ValueError('positive phase voltage and nonnegative current required')
if not -90 <= lag <= 90 or not -180 <= reference <= 180:
raise ValueError('lag within[-90,90] and reference within[-180,180] degrees required')
angles = tuple(math.radians(reference + offset) for offset in (0, -120, 120))
lag_rad = math.radians(lag)
voltages = tuple(cmath.rect(vp, angle) for angle in angles)
currents = tuple(cmath.rect(il, angle - lag_rad) for angle in angles)
try:
line_voltages = tuple(voltages[i] - voltages[(i + 1) % 3] for i in range(3))
phase_powers = tuple(v * i.conjugate() for v, i in zip(voltages, currents))
total = complex(math.fsum(s.real for s in phase_powers), math.fsum(s.imag for s in phase_powers))
apparent = abs(total)
line_magnitudes = tuple(abs(v) for v in line_voltages)
except (OverflowError, ValueError) as error:
raise ValueError('computed power or line voltage not representable') from error
if not all(cmath.isfinite(z) for z in voltages + currents + line_voltages + phase_powers + (total,)):
raise ValueError('computed complex quantity must be finite')
if not all(math.isfinite(x) for x in line_magnitudes + (apparent,)):
raise ValueError('computed magnitude must be finite')
if il > 0 and apparent == 0:
raise ValueError('computed nonzero-load power underflowed to zero')
return {'voltages': voltages, 'currents': currents, 'line_voltages': line_voltages,
'phase_powers': phase_powers, 'total': total, 'apparent_va': apparent,
'power_factor': total.real / apparent if apparent else None}
def _close(actual, expected, abs_tol=1e-9):
return cmath.isclose(actual, expected, rel_tol=2e-13, abs_tol=abs_tol)
def _raises(expected, function, *args, **kwargs):
try:
function(*args, **kwargs)
except expected:
return True
return False
def run_example():
lag = math.degrees(math.atan2(3, 4))
report = balanced_star(120, 5, lag)
# Independent Cartesian hand oracle: each phase V=120+j0, I=4-j3.
hand_p = 3 * Fraction(120) * Fraction(4)
hand_q = 3 * Fraction(120) * Fraction(3)
hand_s = complex(float(hand_p), float(hand_q))
rotated = balanced_star(120, 5, lag, 37)
capacitive = balanced_star(120, 5, -lag)
resistive = balanced_star(120, 5, 0)
zero = balanced_star(120, 0, lag)
inductive = balanced_star(120, 5, 90)
capacitive_pure = balanced_star(120, 5, -90)
peak_formula = sum((math.sqrt(2) * v) * (math.sqrt(2) * i).conjugate() / 2
for v, i in zip(report['voltages'], report['currents']))
wrongly_no_conjugate = sum(v * i for v, i in zip(report['voltages'], report['currents']))
angle_offsets = [math.degrees(cmath.phase(line / phase))
for line, phase in zip(report['line_voltages'], report['voltages'])]
reference_cases = []
for vp in (1, 2, 10, 120):
for il in (0, 1, 3, 5):
for degrees in (-90, -60, -lag, 0, 30, 90):
for reference in (-170, 0, 83):
observed = balanced_star(vp, il, degrees, reference)
# Independent scalar balanced-load formula, no three-phase construction.
radians = degrees * math.pi / 180
expected = complex(3 * vp * il * math.cos(radians), 3 * vp * il * math.sin(radians))
reference_cases.append(_close(observed['total'], expected))
invalid_types = (True, '120', 1 + 0j, None)
invalid_numbers = (float('nan'), float('inf'), -float('inf'), 10 ** 400)
invalid_units = [dict(voltage_unit='kV'), dict(current_unit='mA'), dict(angle_unit='rad'),
dict(amplitude='peak'), dict(connection='delta')]
checks = {
'hand_cartesian_fraction_power_1440_plus_j1080': _close(report['total'], hand_s)
and hand_p == 1440 and hand_q == 1080 and math.isclose(report['apparent_va'], 1800)
and math.isclose(report['power_factor'], 0.8),
'phase_and_line_current_are_rms_magnitudes': all(math.isclose(abs(v), 120) for v in report['voltages'])
and all(math.isclose(abs(i), 5) for i in report['currents']),
'balanced_line_voltage_magnitudes_sqrt_three_times_phase': all(math.isclose(abs(v), math.sqrt(3) * 120)
for v in report['line_voltages']),
'abc_line_voltage_ahead_corresponding_phase_by_30_degrees': all(math.isclose(x, 30, abs_tol=1e-12) for x in angle_offsets),
'balanced_current_sum_zero_with_absolute_ampere_tolerance': abs(sum(report['currents'])) < 1e-12,
'common_reference_rotation_leaves_complex_power_unchanged': _close(rotated['total'], report['total'])
and all(_close(v2, v1 * cmath.rect(1, math.radians(37)), 1e-11)
for v1, v2 in zip(report['voltages'], rotated['voltages'])),
'leading_current_has_negative_reactive_power': _close(capacitive['total'], complex(1440, -1080)),
'resistive_load_has_zero_reactive_power': _close(resistive['total'], complex(1800, 0))
and math.isclose(resistive['power_factor'], 1),
'zero_current_gives_zero_power_and_undefined_power_factor': zero['total'] == 0j
and zero['apparent_va'] == 0 and zero['power_factor'] is None,
'pure_reactive_endpoints_have_near_zero_real_power': _close(inductive['total'], 1800j)
and _close(capacitive_pure['total'], -1800j),
'peak_phasors_need_half_factor_rms_phasors_do_not': _close(peak_formula, report['total']),
'missing_current_conjugate_detected_by_nontrivial_fixture': not _close(wrongly_no_conjugate, report['total'])
and abs(wrongly_no_conjugate) < 1e-9,
'independent_scalar_power_oracle_288_cases': len(reference_cases) == 288 and all(reference_cases),
'power_bilinear_scaling_for_synthetic_magnitudes': _close(balanced_star(240, 5, lag)['total'], 2 * hand_s)
and _close(balanced_star(120, 10, lag)['total'], 2 * hand_s)
and _close(balanced_star(240, 10, lag)['total'], 4 * hand_s),
'zero_negative_voltage_negative_current_and_outside_angles_rejected': all([
_raises(ValueError, balanced_star, 0, 5, lag), _raises(ValueError, balanced_star, -1, 5, lag),
_raises(ValueError, balanced_star, 120, -1, lag), _raises(ValueError, balanced_star, 120, 5, 91),
_raises(ValueError, balanced_star, 120, 5, lag, 181)]),
'exact_type_and_finite_number_contract': all(_raises(TypeError, balanced_star, value, 5, lag) for value in invalid_types)
and all(_raises(ValueError, balanced_star, value, 5, lag) for value in invalid_numbers)
and _raises(TypeError, balanced_star, 120, True, lag)
and _raises(ValueError, balanced_star, 120, 5, float('nan')),
'units_rms_amplitude_and_star_connection_required': all(_raises(ValueError, balanced_star, 120, 5, lag, **kw)
for kw in invalid_units),
'nonfinite_output_and_total_power_underflow_rejected': _raises(ValueError, balanced_star, 1e308, 1e308, 0)
and _raises(ValueError, balanced_star, 5e-324, 5e-324, 0),
}
assert len(checks) == 18 and all(type(v) is bool and v for v in checks.values())
return {'runtime': {'python': platform.python_version(), 'libraries': ['stdlib cmath, math, Fraction; no MATLAB or power simulator executed']},
'contract': {'waveforms': 'balanced sinusoidal steady state, cosine reference, positive abc sequence, star Y load',
'magnitudes': 'VphaseRMS in V, Iline=IphaseRMS in A', 'angles': 'input deg, cmath uses rad; lag=voltage angle-current angle',
'sign': 'current source-to-load entering positive voltage terminal; Q>0 lagging, Q<0 leading',
'power': 'Scomplex=sum(Vphase*conj(Iphase)); P W, Q var, |S| VA',
'allowed': 'V>0,I>=0,lag[-90,90],reference[-180,180],exact V/A/deg/RMS/Y tags'},
'metrics': {'phase_voltage_rms_v': 120, 'line_current_rms_a': 5, 'lag_deg': lag,
'line_to_line_rms_v': [abs(v) for v in report['line_voltages']],
'line_to_phase_angle_deg': angle_offsets, 'active_w': report['total'].real,
'reactive_var': report['total'].imag, 'apparent_va': report['apparent_va'],
'power_factor': report['power_factor'], 'hand_active_w_exact': str(hand_p),
'hand_reactive_var_exact': str(hand_q), 'neutral_current_residual_a': abs(sum(report['currents'])),
'independent_scalar_reference_cases': len(reference_cases)},
'checks': checks,
'limitations': ['No actual power source, load, wiring, meter, safety design, harmonic analysis, simulation library or field measurements.',
'Unbalanced loads, delta conversion, transients, nonsinusoidal/distortion power factor and frequency-dependent models excluded.',
'Finite floating inputs do not ensure exact outputs; reject nonfinite computed quantities and total nonzero-load power rounded to0 only.',
'Some small components can still underflow or cancel; tolerances for selected synthetic cases are not general numerical conditioning guarantees.',
'Common reference rotation does not reverse phase sequence; input magnitude tags cannot detect a caller mislabeled peak value as RMS.']}
if __name__ == '__main__':
print(json.dumps(run_example(), ensure_ascii=False, indent=2))
توان مختلط هر فاز از V ضربدر conjugate جریان محاسبه میشود. بخشهای حقیقی و موهومی با fsum جمع میشوند: S مختلط برابر P+jQ است، P بر حسب وات و Q بر حسب var. اندازهٔ S، توان ظاهری بر حسب VA است؛ خودِ عدد مختلط را نباید با اندازهاش یکی نامید. ضریب توان از P تقسیم بر اندازهٔ S به دست میآید.
ولتاژ فاز باید مثبت و جریان نامنفی باشد؛ فقط int یا float دقیق و متناهی پذیرفته میشود. bool، NaN، بینهایت، عدد مختلطِ ورودی و برچسب واحد ناسازگار رد میشوند. کد تبدیل خودکار kV یا mA ندارد. خروجیِ نامتناهی و صفرشدن کامل توانِ بار غیرصفر بر اثر underflow نیز خطا هستند؛ با این حال تمام خطاهای گردکردن یا حذف مؤلفهٔ بسیار کوچک تشخیص داده نمیشوند.
۴. جواب دستی و هجده گروه بررسی

مرجع دستی را در مختصات دکارتی انتخاب میکنیم: Va برابر ۱۲۰+j۰ ولت و Ia برابر ۴−j۳ آمپر است. اندازهٔ جریان پنج آمپر و lag تقریباً ۳۶٫۸۷ درجه است. مزدوج جریان، ۴+j۳ میشود؛ توان هر فاز ۴۸۰+j۳۶۰ و توان سهفاز ۱۴۴۰+j۱۰۸۰ است. در نتیجه اندازهٔ توان ۱۸۰۰ VA و ضریب توان ۰٫۸ خواهد بود. حساب صحیحِ این مرجع با Fraction جدا ثبت شده است.
{
"runtime": {
"python": "3.14.5",
"libraries": [
"stdlib cmath, math, Fraction; no MATLAB or power simulator executed"
]
},
"contract": {
"waveforms": "balanced sinusoidal steady state, cosine reference, positive abc sequence, star Y load",
"magnitudes": "VphaseRMS in V, Iline=IphaseRMS in A",
"angles": "input deg, cmath uses rad; lag=voltage angle-current angle",
"sign": "current source-to-load entering positive voltage terminal; Q>0 lagging, Q<0 leading",
"power": "Scomplex=sum(Vphase*conj(Iphase)); P W, Q var, |S| VA",
"allowed": "V>0,I>=0,lag[-90,90],reference[-180,180],exact V/A/deg/RMS/Y tags"
},
"metrics": {
"phase_voltage_rms_v": 120,
"line_current_rms_a": 5,
"lag_deg": 36.86989764584402,
"line_to_line_rms_v": [
207.84609690826525,
207.84609690826528,
207.84609690826525
],
"line_to_phase_angle_deg": [
30.000000000000004,
29.999999999999993,
30.000000000000004
],
"active_w": 1440.0,
"reactive_var": 1079.9999999999998,
"apparent_va": 1799.9999999999998,
"power_factor": 0.8000000000000002,
"hand_active_w_exact": "1440",
"hand_reactive_var_exact": "1080",
"neutral_current_residual_a": 2.401779625492033e-15,
"independent_scalar_reference_cases": 288
},
"checks": {
"hand_cartesian_fraction_power_1440_plus_j1080": true,
"phase_and_line_current_are_rms_magnitudes": true,
"balanced_line_voltage_magnitudes_sqrt_three_times_phase": true,
"abc_line_voltage_ahead_corresponding_phase_by_30_degrees": true,
"balanced_current_sum_zero_with_absolute_ampere_tolerance": true,
"common_reference_rotation_leaves_complex_power_unchanged": true,
"leading_current_has_negative_reactive_power": true,
"resistive_load_has_zero_reactive_power": true,
"zero_current_gives_zero_power_and_undefined_power_factor": true,
"pure_reactive_endpoints_have_near_zero_real_power": true,
"peak_phasors_need_half_factor_rms_phasors_do_not": true,
"missing_current_conjugate_detected_by_nontrivial_fixture": true,
"independent_scalar_power_oracle_288_cases": true,
"power_bilinear_scaling_for_synthetic_magnitudes": true,
"zero_negative_voltage_negative_current_and_outside_angles_rejected": true,
"exact_type_and_finite_number_contract": true,
"units_rms_amplitude_and_star_connection_required": true,
"nonfinite_output_and_total_power_underflow_rejected": true
},
"limitations": [
"No actual power source, load, wiring, meter, safety design, harmonic analysis, simulation library or field measurements.",
"Unbalanced loads, delta conversion, transients, nonsinusoidal/distortion power factor and frequency-dependent models excluded.",
"Finite floating inputs do not ensure exact outputs; reject nonfinite computed quantities and total nonzero-load power rounded to0 only.",
"Some small components can still underflow or cancel; tolerances for selected synthetic cases are not general numerical conditioning guarantees.",
"Common reference rotation does not reverse phase sequence; input magnitude tags cannot detect a caller mislabeled peak value as RMS."
]
}
مرجع دوم بدون ساختن سه فاز، P را از ۳VpIp cos(lag) و Q را از ۳VpIp sin(lag) میسازد. ۲۸۸ ترکیبِ دامنه، جریان، lag و مرجع زاویه با آن مقایسه میشوند؛ اینها یک گروه از هجده گروه نامدارند. جواب دستیِ غیرصفر و غیرمقاومتی نیز مانع میشود اشتباه مزدوج پشت یک مثالِ بیشازحد ساده پنهان بماند. هیچکدام اجرای مدار واقعی یا آزمایش دستگاه نیستند.
با چرخاندن مرجع مشترک به اندازهٔ ۳۷ درجه، توان ثابت میماند؛ این کار، معکوسکردن توالی فاز نیست. با منفیکردن lag، Q علامت عوض میکند. برای بار مقاومتی، Q نزدیک صفر و P برابر ۱۸۰۰ وات است. در مرز مثبت و منفی ۹۰ درجه، P از نظر نظری صفر است، ولی برای باقیماندهٔ ممیز شناور از تلورانس مطلق وات استفاده میکنیم؛ برابری دقیقِ اعشاری انتظار مناسبی نیست.
جمع فازور جریانها در مثال متعادل، باقیماندهای در حدود ۲٫۴ ضربدر ده به توان منفی پانزده آمپر دارد. این عدد خطای محاسباتیِ نمونه است؛ اندازهگیری جریان خنثی نیست. کنترل متناهیبودن خروجی، تضمین دقت برای همهٔ مقیاسها یا شرایط عددی نیست. در جریان صفر، توان صفر و ضریب توان در خروجی None است؛ صفر تقسیم بر صفر را ضریب توان یک اعلام نمیکنیم.
آزمون RMS نمونههای ولتاژ به برآورد از پنجرهٔ داده مربوط است؛ اینجا RMS را ورودی فرض میکنیم. قرارداد دسیبل ولتاژ و توان نیز اهمیت واحد و مرجع را نشان میدهد. منابع در ۲۴ مهر ۱۴۰۵ خوانده شدند؛ حقوق درجشدهٔ دو یادداشت MIT بهترتیب ۲۰۰۷ و ۲۰۰۳ و ارائهٔ درسی ۲۰۱۱ است. این تاریخها خبر یا آزمایش تازه نیستند.
۵. چهار پرسش پاسخدار برای بازبینی توان

پرسش اول: ولتاژ خطِ فاز ۱۲۰ ولتی را ۳۶۰ ولت بگیریم؟ پاسخ: خیر؛ در مجموعهٔ متعادل حاضر، اندازهٔ خط رادیکال سه ضربدر ۱۲۰، یعنی حدود ۲۰۷٫۸۴۶ ولت است. این نسبت از تفاضل فازورها میآید.
پرسش دوم: توان سهفازِ جریان ۴−j۳ چند است؟ پاسخ: با فاز ۱۲۰ ولت RMS، ۳×۱۲۰×(۴+j۳) برابر ۱۴۴۰+j۱۰۸۰ میشود؛ بخش حقیقی وات و بخش موهومی var است و اندازهٔ آن ۱۸۰۰ VA خواهد بود.
پرسش سوم: برای جریان پیشفاز، همان Q مثبت را نگه داریم؟ پاسخ: خیر؛ با قرارداد ورود جریان به بار و lag منفیِ مثال، توان ۱۴۴۰−j۱۰۸۰ است. علامت Q باید با قرارداد زاویه و جهت جریان سازگار بماند.
پرسش چهارم: در جریان صفر ضریب توان چند است؟ پاسخ: P و Q و اندازهٔ توان صفرند، ولی نسبت P به اندازهٔ توان تعریف نشده است؛ کد None برمیگرداند. این حالت را از بار مقاومتیِ غیرصفر با ضریب توان یک جدا میکنیم.
منابع و مطالعهٔ بیشتر
- MIT 6.061؛ فصل ۲، توان AC و تبدیل دامنهٔ قله به RMS
- MIT 6.061؛ فصل ۳، شبکهٔ سهفاز متعادل و ولتاژ خط
- Python 3.14؛ زاویهٔ رادیانی، rect، phase و عدد مختلط متناهی
بررسی منابع: ۲۴ مهر ۱۴۰۵. تحلیلها و پیشنهادهای اجرایی، جمعبندی نویسندهاند.

