################################################################################"""`electricpy` Package - Main Module.>>> import electricpy as epFilled with calculators, evaluators, and plotting functions, this package willprovide a wide array of capabilities to any electrical engineer.Built to support operations similar to Numpy and Scipy, this package is designedto aid in scientific calculations."""################################################################################importcmathas_cfrominspectimportgetframeinfoas_getframeinfofrominspectimportstackas_stackfromwarningsimportshowwarningas_showwarningimportmatplotlib.pyplotas_pltimportnumpyas_npfromscipy.integrateimportquadasintegratefrom.versionimportNAME,VERSIONfrom.constantsimport*from.phasorsimportphasor,parallelz__version__=VERSION# Define Cycle Time Function
[docs]deftcycle(ncycles=1,freq=60):r""" Time of Electrical Cycles. Evaluates the time for a number of n cycles given the system frequency. .. math:: t = \frac{n_{cycles}}{freq} Parameters ---------- ncycles: float, optional Number (n) of cycles to evaluate, default=1 freq: float, optional System frequency in Hz, default=60 Returns ------- t: float Total time for *ncycles* Examples -------- >>> import electricpy as ep >>> ep.tcycle(1, freq=60) #Value of ncycles=1 & freq=60 0.016666666666666666 >>> ep.tcycle(1, freq=50) #Value of ncycles=1 & freq=50 0.02 """# Condition Inputsifisinstance(ncycles,_np.ndarray)andisinstance(freq,_np.ndarray):ifncycles.shape!=freq.shape:raiseValueError("ncycles and freq must be the same shape")elifisinstance(ncycles,list)andisinstance(freq,list):iflen(ncycles)!=len(freq):raiseValueError("ncycles and freq must be the same length")ncycles=_np.asarray(ncycles)freq=_np.asarray(freq)if0infreq:raiseZeroDivisionError("Frequency must not be 0")ifnot(freq>0).all():# frequency must be postive valueraiseValueError("Frequency must be postive value")# Evaluate the time for ncyclestime=ncycles/freq# Returnifisinstance(time,_np.ndarray)andlen(time)==1:returntime[0]else:returntime
# Define Reactance Calculator
[docs]defreactance(z,freq=60,sensetivity=1e-12):r""" Capacitance/Inductance from Impedance. Calculates the Capacitance or Inductance in Farads or Henreys (respectively) provided the impedance of an element. Will return capacitance (in Farads) if ohmic impedance is negative :eq:`cap`, or inductance (in Henrys) if ohmic impedance is positive :eq:`ind`. If imaginary: calculate with j factor (imaginary number). .. math:: C = \frac{1}{\omega*Z} :label: cap .. math:: L = \frac{Z}{\omega} :label: ind This requires that the radian frequency is found as follows: .. math:: \omega = 2*\pi*freq where `freq` is the frequency in Hertz. .. note:: It's worth noting here, that the resistance will be found by extracting the real part of a complex value. That is: .. math:: R = Real( R + jX ) Parameters ---------- z: complex The Impedance Provided, may be complex (R+jI) freq: float, optional The Frequency Base for Provided Impedance, default=60 sensetivity: float, optional The sensetivity used to check if a resistance was provided, default=1e-12 Returns ------- float: Capacitance or Inductance of Impedance Examples -------- >>> import electricpy as ep >>> ep.reactance(z=5) # ohms - inductive impedance 0.0132629... """# Evaluate Omegaw=2*_np.pi*freq# Input is Complexifisinstance(z,complex):# Test for Resistanceifabs(z.real)>sensetivity:R=z.realelse:R=0ifz.imag>0:out=z/(w*1j)else:out=1/(w*1j*z)out=abs(out)# Combine with resistance if presentifR!=0:out=(R,out)else:ifz>0:out=z/welse:out=1/(w*z)out=abs(out)# Return Outputreturnout
# Define display function
[docs]defcprint(val,unit=None,label=None,title=None,pretty=True,printval=True,ret=False,decimals=3,round=3):""" Phasor (Complex) Printing Function. This function is designed to accept a complex value (val) and print the value in the standard electrical engineering notation: **magnitude ∠ angle °** This function will print the magnitude in degrees, and can print a unit and label in addition to the value itself. Parameters ---------- val: complex The Complex Value to be Printed, may be singular value, tuple of values, or list/array. unit: string, optional The string to be printed corresponding to the unit mark. label: str, optional The pre-pended string used as a descriptive labeling string. title: str, optional The pre-pended string describing a set of complex values. pretty: bool, optional Control argument to force printed result to a *pretty* format without array braces. default=True printval: bool, optional Control argument enabling/disabling printing of the string. default=True ret: bool, optional Control argument allowing the evaluated value to be returned. default=False decimals: int, optional Replaces `round` argument. Control argument specifying how many decimals of the complex value to be printed. May be negative to round to spaces to the left of the decimal place (follows standard round() functionality). default=3 round: int, optional, DEPRECATED Control argument specifying how many decimals of the complex value to be printed. May be negative to round to spaces to the left of the decimal place (follows standard round() functionality). default=3 Returns ------- numarr: numpy.ndarray The array of values corresponding to the magnitude and angle, values are returned in the form: [[ mag, ang ],...,[ mag, ang ]] where the angles are evaluated in degrees. Examples -------- >>> import numpy as np >>> import electricpy as ep >>> from electricpy import phasors >>> v = phasor(67, 120) >>> ep.cprint(v) 67.0 ∠ 120.0° >>> voltages = np.array([[67,0], ... [67,-120], ... [67,120]]) >>> Vset = ep.phasors.phasorlist( voltages ) >>> ep.cprint(Vset) 67.0 ∠ 0.0° 67.0 ∠ -120.0° 67.0 ∠ 120.0° See Also -------- electricpy.phasors.phasor: Phasor Generating Function electricpy.phasors.phasorlist: Phasor Generating Function for Lists/Arrays electricpy.phasors.phasorz: Impedance Phasor Generator """# Use depricated `round`ifround!=3:decimals=roundcaller=_getframeinfo(_stack()[1][0])# Demonstrate Deprecation Warning_showwarning('`round` argument will be deprecated in favor of `decimals`',DeprecationWarning,caller.filename,caller.lineno)# Interpret as numpy array if simple listifisinstance(val,list):val=_np.asarray(val)# Ensure that input is array# Find length of the input arrayifisinstance(val,_np.ndarray):shp=val.shapetry:row,col=shp# Interpret Shape of Objectexcept(ValueError,IndexError):row=shp[0]col=1sz=val.size# Handle Label as a List or Arrayifisinstance(label,(list,_np.ndarray)):iflen(label)==1:tmp=labelfor_inrange(sz):label=_np.append(label,[tmp])elifsz!=len(label):raiseValueError("Too Few Label Arguments")# Handle Label as Stringelifisinstance(label,str):tmp=labelfor_inrange(sz):label=_np.append(label,[tmp])# Handle Lack of LabeleliflabelisNone:label=_np.array([])for_inrange(sz):label=_np.append(label,None)# Handle all Other Caseselse:raiseValueError("Invalid Label")# Handle Unit as a List or Arrayifisinstance(unit,(list,_np.ndarray)):iflen(unit)==1:tmp=unitfor_inrange(sz):unit=_np.append(unit,[tmp])elifsz!=len(unit):raiseValueError("Too Few Unit Arguments")# Handle Unit as Stringelifisinstance(unit,str):tmp=unitfor_inrange(sz):unit=_np.append(unit,[tmp])# Handle Lack of UnitelifunitisNone:unit=_np.array([])for_inrange(sz):unit=_np.append(unit,None)# Handle all Other Caseselse:raiseValueError("Invalid Unit")# Generate Default Arraysprintarr=_np.array([])# Empty arraynumarr=_np.array([])# Empty array# Operate on List/Arrayforiinrange(row):_val=val[i]_label=label[i]_unit=unit[i]mag,ang_r=_c.polar(_val)# Convert to polar formang=_np.degrees(ang_r)# Convert to degreesmag=_np.around(mag,decimals)# Roundang=_np.around(ang,decimals)# Roundstrg=""if_labelisnotNone:strg+=_label+" "strg+=str(mag)+" ∠ "+str(ang)+"°"if_unitisnotNone:strg+=" "+_unitprintarr=_np.append(printarr,strg)numarr=_np.append(numarr,[mag,ang])# Reshape Arraysprintarr=_np.reshape(printarr,(row,col))numarr=_np.reshape(numarr,(sz,2))# Printifprintvalandrow==1:iftitleisnotNone:print(title)print(strg)elifprintvalandpretty:strg=''start=Trueforiinprintarr:ifnotstart:strg+='\n'strg+=str(i[0])start=FalseiftitleisnotNone:print(title)print(strg)elifprintval:iftitleisnotNone:print(title)print(printarr)# Return if Necessaryifret:return(numarr)elifisinstance(val,(int,float,complex)):# Handle Invalid Unit/LabelifunitisnotNoneandnotisinstance(unit,str):raiseValueError("Invalid Unit Type for Value")iflabelisnotNoneandnotisinstance(label,str):raiseValueError("Invalid Label Type for Value")mag,ang_r=_c.polar(val)# Convert to polar formang=_np.degrees(ang_r)# Convert to degreesmag=_np.around(mag,decimals)# Roundang=_np.around(ang,decimals)# Roundstrg=""iflabelisnotNone:strg+=label+" "strg+=str(mag)+" ∠ "+str(ang)+"°"ifunitisnotNone:strg+=" "+unit# Print values (by default)ifprintval:iftitleisnotNone:print(title)print(strg)# Return values when requestedifret:return([mag,ang])else:raiseValueError("Invalid Input Type")
# Define Phase/Line Converter
[docs]defphaseline(VLL=None,VLN=None,Iline=None,Iphase=None,realonly=None,**kwargs):r""" Line-Line to Line-Neutral Converter. This function is designed to return the phase- or line-equivalent of the voltage/current provided. It is designed to be used when converting delta- to wye-connections and vice-versa. Given a voltage of one type, this function will return the voltage of the opposite type. The same is true for current. .. math:: V_{LL} = \sqrt{3}∠30° * V_{LN} :label: voltages Typical American (United States) standard is to note voltages in Line-to-Line values (VLL), and often, the Line-to-Neutral voltage is of value, this function uses the voltage :eq:`voltages` relation to evaluate either voltage given the other. .. math:: I_{Φ} = \frac{I_{line}}{\sqrt{3}∠30°} :label: currents Often, the phase current in a delta-connected device is of particular interest, and the line-current is provided. This function uses the current :eq:`currents` formula to evaluate phase- and line-current given the opposing term. Parameters ---------- VLL: float, optional The Line-to-Line Voltage; default=None VLN: float, optional The Line-to-Neutral Voltage; default=None Iline: float, optional The Line-Current; default=None Iphase: float, optional The Phase-Current; default=None realonly: bool, optional Replacement of `complex` argument. Control to return value in complex form; default=None complex: bool, optional, DEPRECATED Control to return value in complex form, refer to `realonly` instead. default=None Examples -------- >>> import electricpy as ep >>> ep.cprint(ep.phaseline(VLL=(13.8*ep.k))) # 13.8kV 7967.434 ∠ -30.0° """# Monitor for deprecated inputif'complex'inkwargs.keys():ifrealonlyisNone:realonly=notkwargs['complex']caller=_getframeinfo(_stack()[1][0])# Demonstrate Deprecation Warning_showwarning('`complex` argument will be deprecated in favor of `realonly`',DeprecationWarning,caller.filename,caller.lineno)output=0# Given VLL, convert to VLNifVLLisnotNone:VLN=VLL/(VLLcVLN)output=VLN# Given VLN, convert to VLLelifVLNisnotNone:VLL=VLN*VLLcVLNoutput=VLL# Given Iphase, convert to IlineelifIphaseisnotNone:Iline=Iphase*ILcIPoutput=Iline# Given Iline, convert to IphaseelifIlineisnotNone:Iphase=Iline/ILcIPoutput=Iphase# None given, error encounteredelse:print("ERROR: No value given"+"or innapropriate value"+"given.")return(0)# Auto-detect Complex Valuesifisinstance(output,complex)andrealonlyisNone:realonly=False# Return as complex only when requestedifrealonly:returnabs(output)returnoutput
# Define Power Set Function
[docs]defpowerset(P=None,Q=None,S=None,PF=None,find=''):""" Power Triangle Conversion Function. This function is designed to calculate all values in the set { P, Q, S, PF } when two (2) of the values are provided. The equations in this function are prepared for AC values, that is: real and reactive power, apparent power, and power factor. Parameters ---------- P: float, optional Real Power, unitless; default=None Q: float, optional Reactive Power, unitless; default=None S: float, optional Apparent Power, unitless; default=None PF: float, optional Power Factor, unitless, provided as a decimal value, lagging is positive, leading is negative; default=None find: str, optional Control argument to specify which value should be returned. Returns ------- P: float Calculated Real Power Magnitude Q: float Calculated Reactive Power Magnitude S: float Calculated Apparent Power Magnitude PF: float Calculated Power Factor Examples -------- >>> import electricpy as ep >>> ep.powerset(P=400, Q=300) (400, 300, 500.0, 0.8) >>> ep.powerset(P=400, Q=300, find="PF") 0.8 """# Given P and Qif(PisnotNone)and(QisnotNone):S=_np.sqrt(P**2+Q**2)PF=P/SifQ<0:PF=-PF# Given S and PFelif(SisnotNone)and(PFisnotNone):P=abs(S*PF)Q=_np.sqrt(S**2-P**2)ifPF<0:Q=-Q# Given P and PFelif(PisnotNone)and(PFisnotNone):S=P/PFQ=_np.sqrt(S**2-P**2)ifPF<0:Q=-Q# Given P and Selif(PisnotNone)and(SisnotNone):Q=_np.sqrt(S**2-P**2)PF=P/S# Given Q and Selif(QisnotNone)and(SisnotNone):P=_np.sqrt(S**2-Q**2)PF=P/Selse:raiseValueError("ERROR: Invalid Parameters or too few"+" parameters given to calculate.")# Returnfind=find.upper()iffind=='P':returnPeliffind=='Q':returnQeliffind=='S':returnSeliffind=='PF':returnPFelse:returnP,Q,S,PF
[docs]defslew_rate(V=None,freq=None,SR=None,find=''):""" Slew Rate Calculator. This function is designed to calculate slew rate i.e the change of voltage per unit of time` Parameters ---------- V: float, optional Voltage, Volts; default=None freq: float, optional Frequency, Hz; default=None SR: float, optional Slew Rate, Volts/sec; default=None find: str, optional Control argument to specify which value should be returned. Returns ------- V: float Calculated Volatage freq: float Calculated frequency SR: float Calculated slew rate """ifVisnotNoneandfreqisnotNone:SR=2*_np.pi*V*freqeliffreqisnotNoneandSRisnotNone:V=SR/(2*_np.pi*freq)elifVisnotNoneandSRisnotNone:freq=SR/(2*_np.pi*V)else:raiseValueError("ERROR: Invalid Parameters or too few"+" parameters given to calculate.")iffind=='V':returnVeliffind=='freq':returnfreqeliffind=='SR':returnSRelse:returnV,freq,SR
# Define Non-Linear Power Factor Calculator
[docs]defnon_linear_pf(PFtrue=False,PFdist=False,PFdisp=False):""" Non-Linear Power Factor Evaluator. This function is designed to evaluate one of three unknowns given the other two. These particular unknowns are the arguments and as such, they are described in the representative sections below. .. note:: Also available as `nlinpf`. Parameters ---------- PFtrue: float, exclusive The "True" power-factor, default=None PFdist: float, exclusive The "Distorted" power-factor, default=None PFdisp: float, exclusive The "Displacement" power-factor, default=None Returns ------- float: This function will return the unknown variable from the previously described set of variables. """ifPFtrueisnotNoneandPFdistisnotNoneandPFdispisnotNone:raiseValueError("ERROR: Too many constraints, no solution.")ifPFdistisnotNoneandPFdispisnotNone:returnPFdist*PFdispifPFtrueisnotNoneandPFdispisnotNone:returnPFtrue/PFdispifPFtrueisnotNoneandPFdistisnotNone:returnPFtrue/PFdistraiseValueError("ERROR: Function requires at least two arguments.")
# Alias to original Namenlinpf=non_linear_pf# Define Short-Circuit RL Current Calculator
[docs]defshort_circuit_current(V,Z,t=None,f=None,mxcurrent=True,alpha=None):""" Short-Circuit-Current (ISC) Calculator. The Isc-RL function (Short Circuit Current for RL Circuit) is designed to calculate the short-circuit current for an RL circuit. .. note:: Also available as `iscrl`. Parameters ---------- V: float The absolute magnitude of the voltage. Z: float The complex value of the impedance. (R + jX) t: float, optional The time at which the value should be calculated, should be specified in seconds, default=None f: float, optional The system frequency, specified in Hz, default=None mxcurrent: bool, optional Control variable to enable calculating the value at maximum current, default=True alpha: float, optional Angle specification, default=None Returns ------- Opt 1 - (Irms, IAC, K): The RMS current with maximum DC offset, the AC current magnitude, and the asymmetry factor. Opt 2 - (i, iAC, iDC, T): The Instantaneous current with maximum DC offset, the instantaneous AC current, the instantaneous DC current, and the time-constant T. Opt 3 - (Iac): The RMS current without DC offset. """# Calculate omega, theta, R, and XiffisnotNone:omega=2*_np.pi*felse:omega=NoneR=abs(Z.real)X=abs(Z.imag)theta=_np.arctan(X/R)# If Maximum Current is Desired and No alpha providedifmxcurrentandalphaisNone:alpha=theta-_np.pi/2elifmxcurrentandalphaisnotNone:raiseValueError("ERROR: Inappropriate Arguments Provided.\n"+"Not both mxcurrent and alpha can be provided.")# Calculate Asymmetrical (total) Current if t is not NoneiftisnotNoneandfisnotNone:# Calculate RMS if none of the angular values are providedifalphaisNoneandomegaisNone:# Calculate tautau=t/(1/60)K=_np.sqrt(1+2*_np.exp(-4*_np.pi*tau/(X/R)))IAC=abs(V/Z)Irms=K*IAC# Return ValuesreturnIrms,IAC,KelifalphaisNoneoromegaisNone:raiseValueError("ERROR: Inappropriate Arguments Provided.")# Calculate Instantaneous if all angular values providedelse:# Convert Degrees to Radiansomega=_np.radians(omega)alpha=_np.radians(alpha)theta=_np.radians(theta)# Calculate TT=X/(2*_np.pi*f*R)# seconds# Calculate iAC and iDCiAC=_np.sqrt(2)*V/Z*_np.sin(omega*t+alpha-theta)iDC=-_np.sqrt(2)*V/Z* \
_np.sin(alpha-theta)*_np.exp(-t/T)i=iAC+iDC# Return Valuesreturni,iAC,iDC,Telif(tisnotNoneandfisNone)or(tisNoneandfisnotNone):raiseValueError("ERROR: Inappropriate Arguments Provided.\n"+"Must provide both t and f or neither.")else:Iac=abs(V/Z)returnIac
# Alias to original Nameiscrl=short_circuit_current# Define Voltage Divider Calculator
[docs]defvoltdiv(Vin,R1,R2,Rload=None):r""" Electrical Voltage Divider Function. This function is designed to calculate the output voltage of a voltage divider given the input voltage, the resistances (or impedances) and the load resistance (or impedance) if present. .. math:: V_{out} = V_{in} * \frac{R_2}{R_1+R_2} .. math:: V_{out}=V_{in}*\frac{R_2||R_{load}}{R_1+(R_2||R_{load})} Parameters ---------- Vin: float The Input Voltage, may be real or complex R1: float The top resistor of the divider (real or complex) R2: float The bottom resistor of the divider, the one which the output voltage is measured across, may be either real or complex Rload: float, optional The Load Resistor (or impedance), default=None Returns ------- Vout: float The Output voltage as measured across R2 and/or Rload Examples -------- >>> import electricpy as ep >>> ep.voltdiv(Vin=12, R1=4, R2=8) 8.0 >>> ep.voltdiv(Vin=12, R1=6, R2=12, Rload=12) # R2 and Rload are parallel 6.0 """# Determine whether Rload is givenifRloadisNone:# No Load GivenVout=Vin*R2/(R1+R2)else:# Load was givenRp=R2*Rload/(R2+Rload)Vout=Vin*Rp/(R1+Rp)returnVout
# Define Current Divider Calculator
[docs]defcurdiv(Ri,Rset,Vin=None,Iin=None,Vout=False,combine=True):r""" Electrical Current Divider Function. This function is disigned to accept the input current, or input voltage to a resistor (or impedance) network of parallel resistors (impedances) and calculate the current through a particular element. Parameters ---------- Ri: float The Particular Resistor of Interest, should not be included in the tuple passed to Rset. Rset: float Tuple of remaining resistances (impedances) in network. Vin: float, optional The input voltage for the system, default=None Iin: float, optional The input current for the system, default=None Vout: bool, optional Control argument to enable return of the voltage across the resistor (impedance) of interest (Ri) combine: bool, optional Control argument to force resistance combination. default=True Returns ------- Opt1 - Ii: The Current through the resistor (impedance) of interest Opt2 - (Ii,Vi): The afore mentioned current, and voltage across the resistor (impedance) of interest Examples -------- >>> from electricpy.constants import k >>> import electricpy as ep >>> ep.curdiv(Ri=1*k, Rset=(1*k, 1*k), Iin=12) # 12-amps, split three ways 4.0 >>> ep.curdiv(Ri=1*k, Rset=(1*k, 1*k), Iin=12, Vout=True) # Find Voltage (4.0, 4000.0) """# Validate Tupleifnotisinstance(Rset,tuple):Rset=(Rset,)# Set as Tuple# Calculate The total impedanceifcombine:# Combine tuples, then calculate total resistanceRtot=parallelz(Rset+(Ri,))else:Rtot=parallelz(Rset)# Determine Whether Input was given as Voltage or CurrentifVinisnotNoneandIinisNone:# Vin ProvidedIin=Vin/Rtot# Calculate total currentIi=Iin*Rtot/Ri# Calculate the current of interestelifVinisNoneandIinisnotNone:# Iin providedIi=Iin*Rtot/Ri# Calculate the current of interestelse:raiseValueError("ERROR: Too many or too few constraints provided.")ifVout:# Asked for voltage across resistor of interestVi=Ii*RireturnIi,Vielse:returnIi
# Induction Machine Slip
[docs]definduction_machine_slip(Nr,freq=60,poles=4):r""" Induction Machine slip calculator. This function is used to calculate the slip of an induction machine. .. math:: slip = 1 - \frac{Nr}{120*frac{freq}{poles}} Parameters ---------- Nr: float, Induction Machine Speed (in rpm) freq: int, Supply AC frequency, default=60 poles: Number of poles inside Induction Machine, default=4 Returns ------- slip: float, Induction Machine forward Slip """Ns=(120*freq)/polesreturn(Ns-Nr)/(Ns)
# Define Function to Evaluate Resistance Needed for LED
[docs]defled_resistor(Vsrc,Vfwd=2,Ifwd=20):r""" LED Resistor Calculator. This function will evaluate the necessary resistance value for a simple LED circuit with a voltage source, resistor, and LED. .. math:: R_\text{LED} = \frac{V_\text{SRC} - V_\text{FWD}}{I_\text{FWD}} Parameters ---------- Vsrc: float Source voltage, as measured across both LED and resistor in circuit. Vfwd: float, optional Forward voltage of LED (or series LEDs if available), default=2 Ifwd: float, optional Forward current of LEDs in milliamps, default=20 (milliamps) Returns ------- R: float The resistance value most appropriate for the LED circuit. """# Calculate and Return!R=(Vsrc-Vfwd)/(Ifwd*1000)returnR
# Define Instantaneous Power Calculator
[docs]definstpower(P,Q,t,freq=60):r""" Instantaneous Power Function. This function is designed to calculate the instantaneous power at a specified time t given the magnitudes of P and Q. .. math:: P_{inst} = P+P*cos(2*\omega*t)-Q*sin(2*\omega*t) Parameters ---------- P: float Magnitude of Real Power Q: float Magnitude of Reactive Power t: float Time at which to evaluate freq: float, optional System frequency (in Hz), default=60 Returns ------- float: Instantaneous Power at time t. """# Evaluate omegaw=2*_np.pi*freq# CalculatePinst=P+P*_np.cos(2*w*t)-Q*_np.sin(2*w*t)returnPinst
# Define Delta-Wye Impedance Network Calculator
[docs]defdynetz(delta=None,wye=None,round=None):r""" Delta-Wye Impedance Converter. This function is designed to act as the conversion utility to transform delta-connected impedance values to wye- connected and vice-versa. .. math:: Z_{sum} = Z_{1/2} + Z_{2/3} + Z_{3/1}// Z_1 = \frac{Z_{1/2}*Z_{3/1}}{Z_{sum}}// Z_2 = \frac{Z_{1/2}*Z_{2/3}}{Z_{sum}}// Z_3 = \frac{Z_{2/3}*Z_{3/1}}{Z_{sum}} .. math:: Z_{ms} = Z_1*Z_2 + Z_2*Z_3 + Z_3*Z_1// Z_{2/3} = \frac{Z_{ms}}{Z_1}// Z_{3/1} = \frac{Z_{ms}}{Z_2}// Z_{1/2} = \frac{Z_{ms}}{Z_3} Parameters ---------- delta: tuple of float, exclusive Tuple of the delta-connected impedance values as: { Z12, Z23, Z31 }, default=None wye: tuple of float, exclusive Tuple of the wye-connected impedance valuse as: { Z1, Z2, Z3 }, default=None Returns ------- delta-set: tuple of float Delta-Connected impedance values { Z12, Z23, Z31 } wye-set: tuple of float Wye-Connected impedance values { Z1, Z2, Z3 } """ifdeltaisNoneandwyeisNone:raiseValueError("ERROR: Either delta or wye impedances must be specified.")# Determine which set of impedances was providedifdeltaisnotNoneandwyeisNone:Z12,Z23,Z31=delta# Gather particular impedancesZsum=Z12+Z23+Z31# Find Sum# Calculate Wye ImpedancesZ1=Z12*Z31/ZsumZ2=Z12*Z23/ZsumZ3=Z23*Z31/ZsumZset=(Z1,Z2,Z3)ifroundisnotNone:Zset=_np.around(Zset,round)returnZset# Return Wye ImpedancesifdeltaisNoneandwyeisnotNone:Z1,Z2,Z3=wye# Gather particular impedancesZmultsum=Z1*Z2+Z2*Z3+Z3*Z1Z23=Zmultsum/Z1Z31=Zmultsum/Z2Z12=Zmultsum/Z3Zset=(Z12,Z23,Z31)ifroundisnotNone:Zset=_np.around(Zset,round)returnZset# Return Delta Impedances
# calculating impedance of bridge network
[docs]defbridge_impedance(z1,z2,z3,z4,z5):r""" Bridge Impedance Calculator. The following condition describing the Wheatstone Bridge is utilized to ensure that current through `z5` will be zero. .. math:: z1 \cdot z3 = z2 \cdot z4 .. image:: /static/WheatstoneBridgeCircuit.png Parameters ---------- z1: [float, complex] Bridge impedance 1iscrl z2: [float, complex] Bridge impedance 2 z3: [float, complex] Bridge impedance 3 z4: [float, complex] Bridge impedance 4 z5: [float, complex] Detector impedance or impedance between two bridge branches Returns ------- effective bridge impedance """ifz1*z3==z2*z4:return(z1+z2)*(z3+z4)/(z1+z2+z3+z4)za,zb,zc=dynetz(delta=(z1,z5,z4))ze1=zb+z2ze2=zc+z3returnza+(ze1*ze2)/(ze1+ze2)
# Define Single Line Power Flow Calculator
[docs]defpowerflow(Vsend,Vrec,Xline):r""" Approximated Power-Flow Calculator. This function is designed to calculate the ammount of real power transferred from the sending end to the recieving end of an electrical line given the sending voltage (complex), the receiving voltage (complex) and the line impedance. .. math:: P_{flow}=\frac{|V_{send}|*|V_{rec}|}{X_{line}}*sin(\theta_{send} -\theta_{rec}) Parameters ---------- Vsend: complex The sending-end voltage, should be complex Vrec: complex The receiving-end voltage, should be complex Xline: float The line admitance, should be float Returns ------- pflow: float The Real power transferred from sending-end to receiving-end, positive values denote power flow from send to receive, negative values denote vice-versa. """# Evaluate the Input TermsVs=abs(Vsend)ds=_c.phase(Vsend)Vr=abs(Vrec)dr=_c.phase(Vrec)# Calculate Power Flowpflow=(Vs*Vr)/Xline*_np.sin(ds-dr)returnpflow
# Define Impedance From Power and X/R
[docs]defzsource(S,V,XoR,Sbase=None,Vbase=None,perunit=True):""" Source Impedance Calculator. Used to calculate the source impedance given the apparent power magnitude and the X/R ratio. Parameters ---------- S: float The (rated) apparent power magnitude of the source. This may also be refferred to as the "Short-Circuit MVA" V: float The (rated) voltage of the source terminals, not specifically identified as either Line-to-Line or Line-to- Neutral. XoR: float The X/R ratio rated for the source, may optionally be a list of floats to accomidate sequence impedances or otherwise. Sbase: float, optional The per-unit base for the apparent power. If set to None, will automatically force Sbase to equal S. If set to True will treat S as the per-unit value. Vbase: float, optional The per-unit base for the terminal voltage. If set to None, will automaticlaly force Vbase to equal V. If set to True, will treat V as the per-unit value. perunit: boolean, optional Control value to enable the return of output in per- unit base. default=True Returns ------- Zsource_pu: complex The per-unit evaluation of the source impedance. Will be returned in ohmic (not per-unit) value if *perunit* argument is specified as False. """# Force Sbase and Vbase if neededifVbaseisNone:Vbase=VifSbaseisNone:Sbase=S# Prevent scaling if per-unit already appliedifVbase:Vbase=1ifSbase:Sbase=1# Set to per-unitSpu=S/SbaseVpu=V/Vbase# Evaluate Zsource MagnitudeZsource_pu=Vpu**2/Spu# Evaluate the anglenu=_np.degrees(_np.arctan(XoR))# Conditionally Evaluate Phasor Impedanceifisinstance(nu,(list,_np.ndarray)):Zsource_pu=[]forangleinnu:Zsource_pu.append(phasors(Zsource_pu,angle))else:Zsource_pu=phasors(Zsource_pu,nu)ifnotperunit:Zsource=Zsource_pu*Vbase**2/SbasereturnZsourcereturnZsource_pu
# Define Impedance Decomposer
[docs]defzdecompose(Zmag,XoR):""" Impedance Decomposition Function. A function to decompose the impedance magnitude into its corresponding resistance and reactance using the X/R ratio. It is possible to "neglect" R, or make it a very small number; this is done by setting the X/R ratio to a very large number (X being much larger than R). Parameters ---------- Zmag: float The magnitude of the impedance. XoR: float The X/R ratio (reactance over impedance). Returns ------- R: float The resistance (in ohms) X: float The reactance (in ohms) """# Evaluate ResistanceR=Zmag/_np.sqrt(XoR**2+1)# Evaluate ReactanceX=R*XoR# ReturnreturnR,X
# Define Power Reactance Calculator
[docs]defpowerimpedance(S,V,PF=None,parallel=False,terms=False):r""" Impedance from Apparent Power Formula. Function to determine the ohmic resistance/reactance (impedance) represented by the apparent power (S). .. math:: R = \frac{V^2}{P} \hspace{2cm} X = \frac{V^2}{Q} :label: series-resistance .. math:: Z = \left(\frac{V^2}{S}\right)^* :label: series-impedance .. math:: Z = \left(\frac{V^2}{(3*S)}\right)^* :label: parallel This function can evaluate the component values for both series :eq:`series-resistance`/:eq:`series-impedance` and parallel :eq:`parallel` connected circuits. Parameters ---------- S: complex, float The apparent power of the passive element, may be purely resistive or purely reactive. V: float The operating voltage of the passive element. Note that this is specifically not Line-Line or Line-Neutral voltage, rather the voltage of the element. PF: float, optional The operating Power-Factor, should be specified if S is given as a float (not complex). Positive PF correlates to lagging, negative to leading. default=None parallel: bool, optional Control point to specify whether the ohmic impedance should be returned as series components (False opt.) or parallel components (True opt.). terms: bool, optional Control point to specify whether return should be made as resistance and reactance, or simply the complex impedance. Setting of False will return complex impedance, setting of True will return individual components (R, X). Returns ------- R: float The ohmic resistance required to consume the specified apparent power (S) at the rated voltage (V). X: float The ohmic reactance required to consume the specified apparent power (S) at the rated voltage (V). """# Condition InputsV=abs(V)# Test for Parallel Component Option and Evaluateifisinstance(S,complex)orPFisnotNone:ifPFisnotNone:# Evaluate ElementsP,Q,S,PF=powerset(S=S,PF=PF)else:P=S.realQ=S.imag# Compute Elementsifparallel:Zp=V**2/(3*(P+1j*Q))else:Zp=V**2/(P+1j*Q)Z=_np.conjugate(Zp)R=Z.realX=Z.imag# Conditionally Return as Impedanceifterms:return(R,X)returnZ# Not Complex (just R)R=V**2/SreturnR
# Define function to find VDC setpoint
[docs]defvscdcbus(VLL,Zs,P,Q=0,mmax=0.8,debug=False):""" Voltage Sourced Converter DC Bus Voltage Function. The purpose of this function is to calculate the required DC-bus voltage for a Voltage-Sourced- Converter (VSC) given the desired P/Q parameters and the known source impedance (Vs) of the VSC. Parameters ---------- VLL: complex Line-to-Line voltage on the line-side of the source impedance. Zs: complex The source impedance of the VSC P: float The desired real-power output Q: float, optional The desired reactive-power output, default=0 mmax: float, optional The maximum of the m value for the converter default=0.8 debug: bool, optional Control value to enable printing stages of the calculation, default=False Returns ------- VDC: float The DC bus voltage. """# Determine the Load CurrentIload=_np.conj((P+1j*Q)/(VLL*_np.sqrt(3)))# Evaluate the Terminal VoltageVtln=abs(VLL/_np.sqrt(3)+Iload*Zs)# Find the Peak Terminal VoltageVtpk=_np.sqrt(2)*Vtln# Calculate the VDC valueVDC=2*Vtpk/mmaxifdebug:print("Iload",Iload)print("Vtln",Vtln)print("Vtpk",Vtpk)print("VDC",VDC)returnVDC
# Define kp/ki/w0L calculating function
[docs]defvscgains(Rs,Ls,tau=0.005,freq=60):""" Voltage Sourced Converter Gains Calculator. This function is designed to calculate the kp, ki, and omega-not-L values for a Phase-Lock-Loop based VSC. Parameters ---------- Rs: float The equiv-resistance (in ohms) of the VSC Ls: float The equiv-inductance (in Henrys) of the VSC tau: float, optional The desired time-constant, default=0.005 freq: float, optional The system frequency (in Hz), default=60 Returns ------- kp: float The Kp-Gain Value ki: float The Ki-Gain Value w0L: float The omega-not-L gain value """# Calculate kpkp=Ls/tau# Calculate kiki=kp*Rs/Ls# Calculate w0Lw0L=2*_np.pi*freq*Lsreturnkp,ki,w0L
# Define Peak Calculator
[docs]defpeak(val):r""" Sinusoid RMS to Peak Converter. Provides a readable format to convert an RMS (Root-Mean-Square) value to its peak representation. Performs a simple multiplication with the square-root of two. .. math:: V_{\text{peak}} = \sqrt{2} \cdot V_{\text{RMS}} Examples -------- >>> import electricpy as ep >>> ep.peak(120) 169.7056274847714 """return_np.sqrt(2)*val
# Define RMS Calculator
[docs]defrms(val):r""" Sinusoid Peak to RMS Converter. Provides a readable format to convert a peak value to its RMS (Root-Mean-Square) representation. Performs a simple division by the square-root of two. .. math:: V_{\text{RMS}} = \frac{V_{\text{peak}}}{\sqrt{2}} Examples -------- >>> import electricpy as ep >>> ep.rms(169.7) 119.99602076735711 """returnval*_np.sqrt(0.5)
# Define Normalized Power Spectrum Function
[docs]defwrms(func,dw=0.1,NN=100,quad=False,plot=True,title="Power Density Spectrum",round=3):""" WRMS Function. This function is designed to calculate the RMS bandwidth (Wrms) using a numerical process. Parameters ---------- func: function The callable function to use for evaluation dw: float, optional The delta-omega to be used, default=0.1 NN: int, optional The total number of points, default=100 quad: bool, optional Control value to enable use of integrals default=False plot: bool, optional Control to enable plotting, default=True title: string, optional Title displayed with plot, default="Power Density Spectrum" round: int, optional Control to round the Wrms on plot, default=3 Returns ------- W: float Calculated RMS Bandwidth (rad/sec) """# Define omegaomega=_np.linspace(0,(NN-1)*dw,NN)# Initialize Fraction TermsStot=Sw2=0# Power Density SpectrumSxx=_np.array([])forninrange(NN):# Calculate Power Density SpectrumSxx=_np.append(Sxx,func(omega[n]))Stot=Stot+Sxx[n]Sw2=Sw2+(omega[n]**2)*Sxx[n]ifquad:defintf(w):returnw**2*func(w)num=integrate(intf,0,_np.inf)[0]den=integrate(func,0,_np.inf)[0]# Calculate WW=_np.sqrt(num/den)else:# Calculate WW=_np.sqrt(Sw2/Stot)Wr=_np.around(W,round)# Plot Upon Requestifplot:_plt.plot(omega,Sxx)_plt.title(title)# Evaluate Text Locationx=0.65*max(omega)y=0.80*max(Sxx)_plt.text(x,y,"Wrms: "+str(Wr))_plt.show()# Return Calculated RMS BandwidthreturnW
# Define Hartley's Equation for Data Capacity
[docs]defhartleydata(BW,M):""" Hartley Data Function. Function to calculate Hartley's Law, the maximum data rate achievable for a given noiseless channel. Parameters ---------- BW: float Bandwidth of the data channel. M: float Number of signal levels. Returns ------- C: float Capacity of channel (in bits per second) """C=2*BW*_np.log2(M)returnC
# Define Shannon's Equation For Data Capacity
[docs]defshannondata(BW,S,N):""" Shannon Data Function. Function to calculate the maximum data rate that may be achieved given a data channel and signal/noise characteristics using Shannon's equation. Parameters ---------- BW: float Bandwidth of the data channel. S: float Signal strength (in Watts). N: float Noise strength (in Watts). Returns ------- C: float Capacity of channel (in bits per second) """C=BW*_np.log2(1+S/N)returnC
# Define Per-Unit Impedance Formula
[docs]defzpu(S,VLL=None,VLN=None):r""" Per-Unit Impedance Evaluator. Evaluates the per-unit impedance value given the per-unit power and voltage bases. .. math:: Z_{pu}=\frac{V_{LL}^2}{S} .. math:: Z_{pu}=\frac{(\sqrt{3}*V_{LN})^2}{S} Parameters ---------- S: float The per-unit power base. VLL: float, optional The Line-to-Line Voltage; default=None VLN: float, optional The Line-to-Neutral Voltage; default=None Returns ------- Zbase: float The per-unit impedance base. """ifVLLisNoneandVLNisNone:raiseValueError("ERROR: One voltage must be provided.")ifVLLisnotNone:returnVLL**2/Selse:return(_np.sqrt(3)*VLN)**2/S
# Define Per-Unit Current Formula
[docs]defipu(S,VLL=None,VLN=None,V1phs=None):r""" Per-Unit Current Evaluator. Evaluates the per-unit current value given the per-unit power and voltage bases. .. math:: I_{pu}=\frac{S}{\sqrt{3}*V_{LL}} .. math:: I_{pu}=\frac{S}{3*V_{LN}} Parameters ---------- S: float The per-unit power base. VLL: float, optional The Line-to-Line Voltage; default=None VLN: float, optional The Line-to-Neutral Voltage; default=None V1phs: float, optional The voltage base of the single phase system. Returns ------- Ibase: float The per-unit current base. """ifVLLisNoneandVLNisNone:raiseValueError("ERROR: One voltage must be provided.")ifVLLisnotNone:returnS/(_np.sqrt(3)*VLL)elifVLNisnotNone:returnS/(3*VLN)else:returnS/V1phs
# Define Per-Unit Change of Base Function
[docs]defpuchgbase(quantity,puB_old,puB_new):r""" Per-Unit Change of Base Function. Performs a per-unit change of base operation for the given value constrained by the old base and new base. .. math:: Z_{pu-new}=Z_{pu-old}*\frac{BASE_{OLD}}{BASE_{NEW}} Parameters ---------- quantity: complex Current per-unit value in old base. puB_old: float Old per-unit base. puB_new: float New per-unit base. Returns ------- pu_new: complex New per-unit value. """pu_new=quantity*puB_old/puB_newreturnpu_new
# Define Recomposition Function
[docs]defzrecompose(z_pu,S3phs,VLL=None,VLN=None):""" Impedance from Per-Unit System Evaluator. Function to reverse per-unit conversion and return the ohmic value of an impedance given its per-unit parameters of R and X (as Z). Parameters ---------- z_pu: complex The per-unit, complex value corresponding to the impedance S3phs: float The total three-phase power rating of the system. VLL: float, optional The Line-to-Line Voltage; default=None VLN: float, optional The Line-to-Neutral Voltage; default=None Returns ------- z: complex The ohmic impedance evaluated from the per-unit base. """# Evaluate the per-unit impedancezbase=zpu(S3phs,VLL,VLN)# Evaluate the impedancez=z_pu*zbasereturnz
# Define X/R Recomposition Function
[docs]defrxrecompose(x_pu,XoR,S3phs=None,VLL=None,VLN=None):""" Resistance/Reactance from Per-Unit System Evaluator. Function to reverse per-unit conversion and return the ohmic value of an impedance given its per-unit parameters of X. Parameters ---------- x_pu: float The per-unit, complex value corresponding to the impedance XoR: float The X/R ratio (reactance over impedance). S3phs: float, optional The total three-phase power rating of the system. If left as None, the per-unit values will be set to 1, resulting in an unscaled impedance VLL: float, optional The Line-to-Line Voltage; default=None VLN: float, optional The Line-to-Neutral Voltage; default=None Returns ------- z: complex The ohmic impedance evaluated from the per-unit base. """# Ensure Absolute Valuex_pu=abs(x_pu)# Find R from X/Rr_pu=x_pu/XoR# Compose into zz_pu=r_pu+1j*x_pu# RecomposeifS3phsisNone:returnz_puelse:z=zrecompose(z_pu,S3phs,VLL,VLN)returnz
# Define Generator Internal Voltage Calculator
[docs]defgeninternalv(I,Zs,Vt,Vgn=None,Zm=None,Zmp=None,Zmpp=None,Ip=None,Ipp=None):""" Electric Generator Internal Voltage Evaluator. Evaluates the internal voltage for a generator given the generator's internal impedance and internal mutual coupling impedance values. Parameters ---------- I: complex The current on the phase of interest. Zs: complex The internal impedance of the phase of interest in ohms. Vt: complex The generator's terminal voltage. Vgn: complex, optional The ground-to-neutral connection voltage. Zmp: complex, optional The mutual coupling with the first additional phase impedance in ohms. Zmpp: complex, optional The mutual coupling with the second additional phase impedance in ohms. Ip: complex, optional The first mutual phase current in amps. Ipp: complex, optional The second mutual phase current in amps. Returns ------- Ea: complex The internal voltage of the generator. """# All Parameters ProvidedifZmp==Zmpp==Ip==IppisnotNone:ifVgnisNone:Vgn=0Ea=Zs*I+Zmp*Ip+Zmpp*Ipp+Vt+Vgn# Select Parameters ProvidedelifVgn==Zm==Ip==IppisNone:Ea=Zs*I+Vt# Invalid Parameter Setelse:raiseValueError("Invalid Parameter Set")returnEa
# FFT Coefficient Calculator Function
[docs]deffuncfft(func,minfreq=60,maxmult=15,complex=False):""" FFT Evaluator for Callable Functions. Given the callable function handle for a periodic function, evaluates the harmonic components of the function. Parameters ---------- func: function Callable function from which to evaluate values. minfreq: float, optional Minimum frequency (in Hz) at which to evaluate FFT. default=60 maxmult: int, optional Maximum harmonic (multiple of minfreq) which to evaluate. default=15 complex: bool, optional Control argument to force returned values into complex format. Returns ------- DC: float The DC offset of the FFT result. A: list of float The real components from the FFT. B: list of float The imaginary components from the FFT. """# Apply Nyquist scalingNN=2*maxmult+2# Determine Time from Fundamental FrequencyT=1/minfreq# Generate time range to apply for FFTt,dt=_np.linspace(0,T,NN,endpoint=False,retstep=True)# Evaluate FFTy=_np.fft.rfft(func(t))/t.size# Return Complex Valuesifcomplex:returny# Split out useful valueselse:y*=2returny[0].real,y[1:-1].real,-y[1:-1].imag
[docs]defsampfft(data,dt,minfreq=60.0,complex=False):""" Sample Dataset FFT Evaluator. Given a data array and the delta-t for the data array, evaluates the harmonic composition of the data. Parameters ---------- data: numpy.ndarray Numpy data array containing 1-D values. dt: float Time-difference (delta-t) between data samples. minfreq: float, optional Minimum frequency (in Hz) at which to evaluate FFT. default=60 complex: bool, optional Control argument to force returned values into complex format. Returns ------- DC: float The DC offset of the FFT result. A: list of float The real components from the FFT. B: list of float The imaginary components from the FFT. """# Calculate TermsFR=1/(dt*len(data))NN=1//(dt*minfreq)# Test for Invalid SystemifFR>minfreq:raiseValueError("Too few data samples to evaluate FFT at specified minimum ""frequency.")elifFR==minfreq:# Evaluate FFTy=_np.fft.rfft(data)/len(data)else:# Slice data array to appropriate fundamental frequencycut_data=data[:int(NN)]# Evaluate FFTy=_np.fft.rfft(cut_data)/len(cut_data)# Return Complex Valuesifcomplex:return(y)# Split out useful valueselse:y*=2returny[0].real,y[1:-1].real,-y[1:-1].imag
# Define FFT Plotting Function
[docs]deffftplot(dc,real,imag=None,title="Fourier Coefficients"):""" FFT System Plotter. Plotting function for FFT (harmonic) values, plots the DC, Real, and Imaginary components. Parameters ---------- dc: float The DC offset term real: list of float Real terms of FFT (cosine terms) imag: list of float, optional Imaginary terms of FFT (sine terms) title: str, optional String appended to plot title, default="Fourier Coefficients" Returns ------- matplotlib.pyplot: Plotting object to be used for additional configuration or plotting. """# Define Range values for plotsrng=range(1,len(real)+1,1)xtic=range(0,len(real)+1,1)# Set up Argumentsa0x=[0,0]a0y=[0,dc/2]# Plot_plt.title(title)_plt.plot(a0x,a0y,'g',label="DC-Term")_plt.stem(rng,real,linefmt='r',markerfmt='ro',label="Real-Terms",use_line_collection=True)ifimagisnotNone:_plt.stem(rng,imag,linefmt='b',markerfmt='bo',label="Imaginary-Terms",use_line_collection=True)_plt.xlabel("Harmonics (Multiple of Fundamental)")_plt.ylabel("Harmonic Magnitude")_plt.axhline(0.0,color='k')_plt.legend()if(len(xtic)<50):_plt.xticks(xtic)return_plt
# Define FFT Composition Plotting Function
[docs]deffftsumplot(dc,real,imag=None,freq=60,xrange=None,npts=1000,plotall=False,title="Fourier Series Summation"):""" FFT Summation Plotter. Function to generate the plot of the sumed FFT results. Parameters ---------- dc: float The DC offset term real: list of float Real terms of FFT (cosine terms) imag: list of float Imaginary terms of FFT (sine terms) freq: float, optional Fundamental (minimum nonzero) frequency in Hz, default=60 xrange: list of float, optional List of two floats containing the minimum time and the maximum time. npts: int, optional Number of time step points, default=1000 title: str, optional String appended to plot title, default="Fourier Series Summation" Returns ------- matplotlib.pyplot: Plotting object to be used for additional configuration or plotting. """# Determine the number (N) of termsN=len(real)# Determine the system period (T)T=1/freq# Generate Domain ArrayifxrangeisNone:x=_np.linspace(0,T,npts)else:x=_np.linspace(xrange[0],xrange[1],npts)# Initialize output with DC termyout=_np.ones(len(x))*dc# Plot each iteration of the Fourier Seriesforkinrange(1,N):ifplotall:_plt.plot(x,yout)yout+=real[k-1]*_np.cos(k*2*_np.pi*x/T)ifimagisnotNone:yout+=imag[k-1]*_np.sin(k*2*_np.pi*x/T)_plt.plot(x,yout)_plt.title(title)_plt.xlabel("Time (seconds)")_plt.ylabel("Magnitude")return_plt
# Define harmonic system generation function
[docs]defharmonics(real,imag=None,dc=0,freq=60,domain=None):""" Harmonic Function Generator. Generate a function or dataset for a harmonic system given the real (cosine), imaginary (sine), and DC components of the system. Parameters ---------- real: list of float The real (cosine) component coefficients for the harmonic system. imag: list of float, optional The imaginary (sine) component coefficients for the harmonic system. dc: float, optional The DC offset for the harmonic system, default=0 freq: float, optional The fundamental frequency of the system in Hz, default=60 domain: list of float, optional Domain of time samples at which to calculate the harmonic system, must be array-like, will cause function to return numpy array instead of function object. Returns ------- system: function Function object handle which can be used to call the function to evaluate the harmonic system at specified times. """# Validate Inputsifnotisinstance(real,(list,_np.ndarray)):raiseValueError("Argument *real* must be array-like.")ifimagisnotNoneandnotisinstance(imag,(list,_np.ndarray)):raiseValueError("Argument *imag* must be array-like.")# Calculate Omegaw=2*_np.pi*freqdef_harmonic_(t):out=dcforkinrange(len(real)):# Evaluate Current CoefficientA=real[k]ifimagisnotNone:B=imag[k]else:B=0m=k+1# Calculate Outputout+=A*_np.cos(m*w*t)+B*_np.sin(m*w*t)# Return Valuereturn(out)ifdomainisNone:return_harmonic_# Return as callable for external useelse:return_harmonic_(domain)
# Define Single Phase Motor Startup Capacitor Formula
[docs]defmotorstartcap(V,I,freq=60):""" Single Phase Motor Starting Capacitor Function. Function to evaluate a reccomended value for the startup capacitor associated with a single phase motor. Parameters ---------- V: float Magnitude of motor terminal voltage in volts. I: float Magnitude of motor no-load current in amps. freq: float, optional Motor/System frequency, default=60. Returns ------- C: float Suggested capacitance in Farads. """# Condition InputsI=abs(I)V=abs(V)# Calculate CapacitancereturnI/(2*_np.pi*freq*V)
# Define Power Factor Correction Function
[docs]defpfcorrection(S,PFold,PFnew,VLL=None,VLN=None,V=None,freq=60):""" Power Factor Correction Function. Function to evaluate the additional reactive power and capacitance required to achieve the desired power factor given the old power factor and new power factor. Parameters ---------- S: float Apparent power consumed by the load. PFold: float The current (old) power factor, should be a decimal value. PFnew: float The desired (new) power factor, should be a decimal value. VLL: float, optional The Line-to-Line Voltage; default=None VLN: float, optional The Line-to-Neutral Voltage; default=None V: float, optional Voltage across the capacitor, ignores line-to-line or line-to-neutral constraints. default=None freq: float, optional System frequency, default=60 Returns ------- C: float Required capacitance in Farads. Qc: float Difference of reactive power, (Qc = Qnew - Qold) """# Condition InputsS=abs(S)# Calculate Initial TermsPold=S*PFoldQold=_np.sqrt(S**2-Pold**2)# Evaluate Reactive Power RequirementsScorrected=Pold/PFnewQcorrected=_np.sqrt(Scorrected**2-Pold**2)Qc=Qold-Qcorrected# Evaluate Capacitance Based on Voltage InputifVLL==VLN==VisNone:raiseValueError("One voltage must be specified.")elifVLNisnotNone:C=Qc/(2*_np.pi*freq*3*VLN**2)else:ifVLLisnotNone:V=VLLC=Qc/(2*_np.pi*freq*V**2)# Return ValuereturnC,Qc
# Define Apparent Power / Voltage / Current Relation Function
[docs]defacpiv(S=None,I=None,VLL=None,VLN=None,V=None,PF=None):""" AC Power-Voltage-Current Relation Function. Relationship function to return apparent power, voltage, or current in one of various forms. Parameters ---------- S: complex, optional Apparent power, may be single or three-phase, specified in volt-amps (VAs) I: complex, optional Phase current in amps VLL: complex, optional Line-to-Line voltage in volts VLN: complex, optional Line-to-Neutral voltage in volts V: complex, optional Single-phase voltage in volts PF: float, optional Power factor to condition the apparent power to an appropriate complex value. Returns ------- S: complex Apparent power, returned only if one voltage and current is specified I: complex Phase current, returned only if one voltage and apparent power is specified VLL: complex Line-to-Line voltage, returned only if current and apparent power specified, returned as set with other voltages in form: (VLL, VLN, V) VLN: complex Line-to-Neutral voltage, returned only if current and apparent power specified, returned as set with other voltages in form: (VLL, VLN, V) V: complex Single-phase voltage, returned only if current and apparent power specified, returned as set with other voltages in form: (VLL, VLN, V) PF: float, optional Supporting argument to convert floating-point apparent power to complex representation. Examples -------- >>> import electricpy as ep >>> ep.acpiv(S=550, V=167) 3.2934131736526946 >>> ep.acpiv(S=550, I=3.2934131736526946) (96.4174949546675, 55.66666666666667, 167.0) """# Validate InputsifS==IisNone:raiseValueError("To few arguments.")# Convert Apparent Power to ComplexifPFisnotNone:S=S*PF+1j*_np.sqrt(S**2-(S*PF)**2)# Solve Single-PhaseifVisnotNone:ifSisNone:# Solve for Apparent PowerS=V*_np.conj(I)returnSelse:# Solve for CurrentI=_np.conj(S/V)returnI# Solve Line-to-LineelifVLLisnotNone:ifSisNone:# Solve for Apparent PowerS=_np.sqrt(3)*VLL*_np.conj(I)returnSelse:# Solve for CurrentI=_np.conj(S/(_np.sqrt(3)*VLL))returnI# Solve Line-to-NeutralelifVLNisnotNone:ifSisNone:# Solve for Apparent PowerS=3*VLN*_np.conj(I)returnSelse:# Solve for CurrentI=_np.conj(S/(3*VLN))returnI# Solve for Voltageselse:V=S/_np.conj(I)VLL=S/(_np.sqrt(3)*_np.conj(I))VLN=S/(3*_np.conj(I))returnVLL,VLN,V
# Define Primary Ratio Function
[docs]defprimary(val,Np,Ns=1,invert=False):""" Electrical Transformer Primary Evaluator. Returns a current or voltage value reflected across a transformer with a specified turns ratio Np/Ns. Converts to the primary side. Parameters ---------- val: complex Value to be reflected across transformer. Np: float Number of turns on primary side. Ns: float, optional Number of turns on secondary side. invert: bool, optional Control argument to invert the turns ratio, used when reflecting current across a voltage transformer, or voltage across a current transformer. Returns ------- reflection: complex The reflected value referred to the primary side according to Np and Ns. """ifinvert:returnval*Ns/Npreturnval*Np/Ns
# Define Secondary Ratio Function
[docs]defsecondary(val,Np,Ns=1,invert=False):""" Electrical Transformer Secondary Evaluator. Returns a current or voltage value reflected across a transformer with a specified turns ratio Np/Ns. Converts to the secondary side. Parameters ---------- val: complex Value to be reflected across transformer. Np: float Number of turns on primary side. Ns: float, optional Number of turns on secondary side. invert: bool, optional Control argument to invert the turns ratio, used when reflecting current across a voltage transformer, or voltage across a current transformer. Returns ------- reflection: complex The reflected value referred to the secondary side according to Np and Ns. """ifinvert:returnval*Np/Nsreturnval*Ns/Np
[docs]deftap_changing_transformer(Vgen,Vdis,Pload,Qload,R,X):r""" Calculate Turn Ratio of Load Tap Changing Transformer. The purpose of a tap changer is to regulate the output voltage of a transformer. It does this by altering the number of turns in one winding and thereby changing the turns ratio of the transformer .. math:: \sqrt{\frac{Vgen^2}{Vgen \cdot Vdis - R \cdot P - X \cdot Q}} Parameters ---------- Vgen: float Generating station voltage Vdis: float Distribution network voltage Pload: float Transmission line load active power in Watt Qload: float Transmission line load reactive power in VAR R: float Resistance of transmission line X: float Reactance of transmission line Returns ------- ts: float Turns ration of transformer """# Evaluate the turns ratiots=(Vgen*Vgen)/(Vgen*Vdis-(R*Pload+X*Qload))returnpow(ts,0.5)
[docs]defsuspension_insulators(number_capacitors,capacitance_ratio,Voltage):r""" Discrete Capacitors Voltage in a Suspension Insulator Strain. To perform the calculations described here, the following formulas are satisfied, and used to construct a matrix used to solve for :math:`V_i \text{i in range(1,n)}`. .. math:: \sum_{i=1}^{n-2} V_{i} + V_{n-1} \cdot (1+m) - V_{n} \cdot m=0 .. math:: \sum_{i=1}^{n} V_{i} = V_{\text{transmission line}} .. image:: /static/SuspensionInuslator.png `Additional Information <https://electrical-engineering-portal.com/download-center/books-and-guides/power-substations/insulator-pollution>`_ Parameters ---------- number_capacitors: int Number of disk capacitors hung to transmission line capacitance_ratio: float Ratio of disk capacitance and pin to pole air capacitance Voltage: float Voltage difference between the transmission line and ground Returns ------- string_efficiency: float String efficiency of capacitive disks capacitor_disk_voltages: float Voltage across each capacitive disk starting from top to bottom """m=_np.zeros((number_capacitors,number_capacitors))# Iterate over capacitorsforiinrange(number_capacitors-1):# Iterate over capacitorsforjinrange(number_capacitors-1):# If inner iteration is less than outer iterationifi>=j:m[i,j]=1/capacitance_ratioforiinrange(number_capacitors-1):m[i,i]=(1+1/capacitance_ratio)m[i,i+1]=-1m[number_capacitors-1,:]=1v=_np.zeros((number_capacitors,1))v[number_capacitors-1,0]=Voltagecapacitor_disk_voltages=_np.matmul(_np.linalg.inv(m),v)string_efficiency=((Voltage*100)/(number_capacitors*capacitor_disk_voltages[-1,0]))returncapacitor_disk_voltages,string_efficiency
# Define Natural Frequency/Resonant Frequency Calculator
[docs]defnatfreq(C,L,Hz=True):r""" Natural Frequency Evaluator. Evaluates the natural frequency (resonant frequency) of a circuit given the circuit's C and L values. Defaults to returning values in Hz, but may also return in rad/sec. .. math:: freq=\frac{1}{\sqrt{L*C}*(2*\pi)} Parameters ---------- C: float Capacitance Value in Farads. L: float Inductance in Henries. Hz: bool, optional Control argument to set return value in either Hz or rad/sec; default=True. Returns ------- freq: float Natural (Resonant) frequency, will be in Hz if argument *Hz* is set True (default), or rad/sec if argument is set False. """# Evaluate Natural Frequency in rad/secfreq=1/_np.sqrt(L*C)# Convert to Hz as requestedifHz:freq=freq/(2*_np.pi)return(freq)
# Define Voltage/Current Unbalance Equation
[docs]defunbalance(A,B,C,all=False):""" Voltage/Current Unbalance Function. Performs a voltage/current unbalance calculation to determine the maximum current/voltage unbalance. Returns result as a decimal percentage. Parameters ---------- A: float Phase-A value B: float Phase-B value C: float Phase-C value all: bool, optional Control argument to require function to return all voltage/current unbalances. Returns ------- unbalance: float The unbalance as a percentage of the average. (i.e. 80% = 0.8) """# Condition InputsA=abs(A)B=abs(B)C=abs(C)# Gather Averageavg=(A+B+C)/3# Determine VariancedA=abs(A-avg)dB=abs(B-avg)dC=abs(C-avg)# Gather Maximum Variationmx=max(dA,dB,dC)# Calculate Maximum Variationunbalance=mx/avg# Return Resultsifall:returndA/avg,dB/avg,dC/avgelse:returnunbalance
# Define Cosine Filter Function
[docs]defcosfilt(arr,Srate,domain=False):""" Cosine Filter Function. Cosine Filter function for filtering a dataset representing a sinusoidal function with or without harmonics to evaluate the fundamental value. Parameters ---------- arr: numpy.ndarray The input data array. Srate: int Sampling rate for dataset, specified in number of values per fundamental cycle. domain: bool, optional Control argument to force return of x-axis array for the filtered data. Returns ------- cosf: numpy.ndarray Cosine-filtered data xarray: numpy.ndarray X-axis array for the filtered data. """# Evaluate index setind=_np.arange(Srate-1,len(arr)-1)# Define Cosine Coefficient Functiondefcos(k,Srate):return_np.cos(2*_np.pi*k/Srate)# Calculate Constantconst=2/Srate# Iteratively Calculatecosf=0forkinrange(0,Srate-1):slc=(ind-(Srate-1))+kcosf+=cos(k,Srate)*arr[slc]# Scalecosf=const*cosf# Return Cosine-Filtered Arrayifdomain:xarray=_np.linspace(Srate+Srate/4-1,len(arr)-1,len(cosf))xarray=xarray/Sratereturncosf,xarrayreturncosf
# Define Sine Filter Function
[docs]defsinfilt(arr,Srate,domain=False):""" Sine Filter Function. Sine Filter function for filtering a dataset representing a sinusoidal function with or without harmonics to evaluate the fundamental value. Parameters ---------- arr: numpy.ndarray The input data array. Srate: int Sampling rate for dataset, specified in number of values per fundamental cycle. domain: bool, optional Control argument to force return of x-axis array for the filtered data. Returns ------- sinf: numpy.ndarray Sine-filtered data xarray: numpy.ndarray X-axis array for the filtered data. """# Evaluate index setind=_np.arange(Srate-1,len(arr)-1)# Define Cosine Coefficient Functiondefsin(k,Srate):return_np.sin(2*_np.pi*k/Srate)# Calculate Constantconst=2/Srate# Iteratively Calculatesinf=0forkinrange(0,Srate-1):slc=(ind-(Srate-1))+ksinf+=sin(k,Srate)*arr[slc]# Scalesinf=const*sinf# Return Cosine-Filtered Arrayifdomain:xarray=_np.linspace(Srate+Srate/4-1,len(arr)-1,len(sinf))xarray=xarray/Sratereturnsinf,xarrayreturnsinf
# Define Characteristic Impedance Calculator
[docs]defcharacterz(R,G,L,C,freq=60):r""" Characteristic Impedance Calculator. Function to evaluate the characteristic impedance of a system with specefied line parameters as defined. System uses the standard characteristic impedance equation :eq:`Zc`. .. math:: Z_c = \sqrt{\frac{R+j\omega L}{G+j\omega C}} :label: Zc Parameters ---------- R: float Resistance in ohms. G: float Conductance in mhos (siemens). L: float Inductance in Henries. C: float Capacitance in Farads. freq: float, optional System frequency in Hz, default=60 Returns ------- Zc: complex Charcteristic Impedance of specified line. """# Evaluate omegaw=2*_np.pi*freq# Evaluate ZcZc=_np.sqrt((R+1j*w*L)/(G+1j*w*C))return(Zc)
# Define propagation_constants for long transmission line
[docs]defpropagation_constants(z,y,length):r""" Transaction Line Propagation Constant Calculator. This function will evaluate the propagation constants for a long transmission line whose properties are governed by the differential equation: .. math:: \frac{d^2V}{dx^2} = \gamma V From the above equation, the following formulas are derived to evaluate the desired constants. .. math:: \gamma = \sqrt( z * y ) .. math:: Z_{\text{surge}} = \sqrt( z / y ) .. math:: \alpha = \Re{ \gamma } .. math:: \beta = \Im{ \gamma } Parameters ---------- z: complex Impedence of the transmission line: R+j*2*pi*f*L y: complex Admitance of the transmission line g+j*2*pi*f*C Returns ------- params: dict Dictionary of propagation constants including: gamma: Propagation constant zc: Surge impedance alpha: Attenuation constant beta: Imaginary portion of gamma """# Validate the line length is substantial enough for calculationifnot(length>500):raiseValueError("Long transmission line length should be grater than 500km")gamma=_np.sqrt(z*y)alpha=gamma.realbeta=gamma.imagzc=_np.sqrt(z/y)params={'gamma':gamma,'alpha':alpha,'beta':beta,'Surge_impedance':zc}returnparams
# Define De Calculator for Transmission Lines
[docs]defde_calc(rho,freq=60):r""" De Transmission Line Value Calculator. Simple calculator to find the De value for a line with particular earth resistivity (rho). .. math:: D_e=D_{e_{\text{constant}}}\sqrt{\frac{\rho}{freq}} Parameters ---------- rho: float Earth resistivity (in ohm-meters), may also be passed a string in the set: {SEA, SWAMP, AVG,AVERAGE,DAMP,DRY,SAND,SANDSTONE} freq: float, optional System frequency in Hertz, default=60 """# If Descriptive String Provided, Use to Determine Rhoifisinstance(rho,str):rho=rho.upper()try:rho=RHO_VALUES[rho]exceptKeyError:raiseValueError("Invalid Earth Resistivity string try to select \ from set of (SEA, SWAMP, AVG, AVERAGE, DAMP, DRY, SAND, SANDSTONE")# Calculate DeDe=De0*_np.sqrt(rho/freq)returnDe
# Define Impedance Per Length Calculator
[docs]defzperlength(Rd=None,Rself=None,Rac=None,Rgwac=None,De=None,rho="AVG",Ds=None,Dsgw=None,dia_gw=None,Dab=None,Dbc=None,Dca=None,Dagw=None,Dbgw=None,Dcgw=None,resolve=True,freq=60):""" Transmission Line Impedance (RL) Calculator. Simple impedance matrix generator to provide the full impedance per length matrix. Parameters ---------- Rd: float, optional Resistance Rd term in ohms, will be generated automatically if set to None, default=None Rself: float, optional Self Resistance term in ohms. Rac: float, optional AC resistance in ohms. Rgwac: float, optional Ground-Wire AC resistance in ohms. De: float, optional De term, in feet, if None provided, and `rho` parameter is specified, will interpretively be calculated. rho: float, optional Earth resistivity in ohm-meters. default="AVG" Ds: float, optional Distance (self) for each phase conductor in feet, commonly known as GMD. Dsgw: float, optional Distance (self) for the ground wire conductor in feet, commonly known as GMD. dia_gw: float, optional Ground-Wire diameter in feet, may be used to calculate an approximate Dsgw if no Dsgw is provided. Dab: float, optional Distance between phases A and B, in feet. Dbc: float, optional Distance between phases B and C, in feet. Dca: float, optional Distance between phases C and A, in feet. Dagw: float, optional Distance between phase A and ground conductor, in feet. Dbgw: float, optional Distance between phase B and ground conductor, in feet. Dcgw: float, optional Distance between phase C and ground conductor, in feet. resolve: bool, optional Control argument to specify whether the resultant ground-wire inclusive per-length impedance matrix should be reduced to a 3x3 equivalent matrix. default=True freq: float, optional System frequency in Hertz. """# Start with Empty ArraysRperlen=0Lperlen=0# Generate RdifRdisNone:Rd=freq*carson_r# Generate Dsgw if Not ProvidedifDsgwisNoneanddia_gwisnotNone:Dsgw=_np.exp(-1/4)*dia_gw/2# Generate Real PartifRd>0:# Generate Rself if not ProvidedifRselfisNone:# Validate Inputsifnotall((Rd,Rac)):raiseValueError("Too few arguments")Rself=Rac+Rd# Generate RperLength MatrixRperlen=_np.array([[Rself,Rd,Rd],[Rd,Rself,Rd],[Rd,Rd,Rself]])# Add GW effects If Necessaryifall((Rgwac,Dsgw,Dagw,Dbgw,Dcgw)):# Calculate RselfgwRselfgw=Rgwac+Rd# Append Right-Most ColumnRperlen=_np.append(Rperlen,[[Rd],[Rd],[Rd]],axis=1)# Append New RowRperlen=_np.append(Rperlen,[[Rd,Rd,Rd,Rselfgw]],axis=0)# Generate Imaginary Partifany((De,Ds,rho)):# Validate Inputsifnotall((Dab,Dbc,Dca)):raiseValueError("Distance Terms [Dab,Dbc,Dca] Required")ifDsisNone:raiseValueError("Distance Self (Ds) Required")# De must be generatedifDeisNone:ifrhoisNone:raiseValueError("Too few arguments")De=de_calc(rho,freq)# Generate LperLength MatrixLperlen=_np.array([[_np.log(De/Ds),_np.log(De/Dab),_np.log(De/Dca)],[_np.log(De/Dab),_np.log(De/Ds),_np.log(De/Dbc)],[_np.log(De/Dca),_np.log(De/Dbc),_np.log(De/Ds)]])# Add GW effects If Necessaryifall((Rgwac,Dsgw,Dagw,Dbgw,Dcgw)):# Append Right-Most ColumnLperlen=_np.append(Lperlen,[[_np.log(De/Dagw)],[_np.log(De/Dbgw)],[_np.log(De/Dcgw)]],axis=1)# Append New RowLperlen=_np.append(Lperlen,[[_np.log(De/Dagw),_np.log(De/Dbgw),_np.log(De/Dcgw),_np.log(De/Dsgw)]],axis=0)Lperlen=Lperlen*(1j*u0*freq)# Add Real and Imaginary PartsZperlen=Rperlen+Lperlen# Resolve to 3x3 Matrix if Neededifresolveandall((Rgwac,Dsgw,Dagw,Dbgw,Dcgw)):# Perform Slicing to Retrieve Useful ArraysZa=Zperlen[:3,:3]Zb=Zperlen[:3,3:4]Zc=Zperlen[3:4,:3]Zd=Zperlen[3:4,3:4]# Calculate New (3x3) Equivalent ZperlenZperlen=Za-_np.dot(Zb,_np.dot(_np.linalg.inv(Zd),Zc))returnZperlen
# Define Transposition Matrix Formula
[docs]deftransposez(Zeq,fabc=1/3,fcab=1/3,fbca=1/3,linelen=1):r""" Transmission Matrix Equivalent Transposition Calculator. Given the impedance matrix and the percent of the line spent in each transposition relation (ABC, CAB, and BCA). .. math:: f_{abc}Z_{eq}+f_{cab}R_p^{-1}\cdot Z_{eq}\cdot R_p+ f_{bca}Z_{eq}R_p\cdot Z_{eq}\cdot R_p^{-1} where: .. math: R_p=\begin{bmatrix}\\ 0 & 0 & 1 \\ 1 & 0 & 0 \\ 0 & 1 & 0 \\ \end{bmatrix} Parameters ---------- Zeq: array_like Per-Length (or total length) line impedance in ohms. fabc: float, optional Percentage of line set with phase relation ABC, default=1/3 fcab: float, optional Percentage of line set with phase relation CAB, default=1/3 fbca: float, optional Percentage of line set with phase relation BCA, default=1/3 linelen: Length of line (unitless), default=1 """# Condition InputZeq=_np.asarray(Zeq)# Define Rp ArrayRp=_np.array([[0,0,1],[1,0,0],[0,1,0]])# Define Inverse Rp Array_Rp=_np.linalg.inv(Rp)Zeq=fabc*Zeq+fcab*(_Rp.dot(Zeq.dot(Rp)))+ \
fbca*(Rp.dot(Zeq.dot(_Rp)))Zeq=Zeq*linelenreturnZeq
# Define GMD Calculator
[docs]defgmd(Ds,*args):r""" GMD (Geometric Mean Distance) Calculator. Calculates the GMD (Geometric Mean Distance) for a system with the parameters of a list of arguments. .. math:: GMD=(D_s*D_1*\ddot*D_n)^{\frac{1}{1+n}} Parameters ---------- Ds: float Self distance (unitless), normally provided from datasheet/reference *args: floats, optional Remaining set of distance values (unitless) """# Find the Root from Number of Argumentsroot=len(args)+1# Calculate the Root Termgmdx=Dsfordistinargs:gmdx*=dist# Apply Root CalculationGMD=gmdx**(1/root)returnGMD
# Define Power-Factor Voltage/Current Relation
[docs]defvipf(V=None,I=None,PF=1,find=''):""" Voltage / Current / Power Factor Solver. Given two of the three parameters, will solve for the third; beit voltage, current, or power factor. Parameters ---------- V: complex System voltage (in volts), default=None I: complex System current (in amps), default=None PF: float System power factor, (+)ive values denote leading power factor, (-)ive values denote lagging power factor; default=1 find: str, optional Control argument to specify which value should be returned. Returns ------- V: complex System voltage (in volts), default=None I: complex System current (in amps), default=None PF: float System power factor, (+)ive values denote leading power factor, (-)ive values denote lagging poer factor; default=1 Examples -------- >>> import electricpy as ep >>> # Demonstrate the generic functionality >>> ep.vipf(V=480, I=ep.phasors.phasor(20, 120)) (480, (-9.999999999999996+17.320508075688775j), -0.499999...) >>> # Find the power factor >>> ep.vipf(V=480, I=ep.phasors.phasor(20, 120), find="PF") -0.49999... """# Test to find Voltageifisinstance(V,float)andisinstance(I,complex):phi=-_np.sign(PF)*_np.arccos(PF)V=V*_np.exp(-1j*phi)# Test to find Currentelifisinstance(V,complex)andisinstance(I,float):phi=_np.sign(PF)*_np.arccos(PF)I=I*_np.exp(-1j*phi)# Test to find Power Factorelifall([V,I]):phi=_np.angle(V)-_np.angle(I)PF=_np.cos(phi)# Failed Modeelse:raiseValueError("All values must be provided.")# Returnfind=find.upper()iffind=='V':returnViffind=='I':returnIiffind=='PF':returnPFreturnV,I,PF
# Define Synchronous Speed Calculator
[docs]defsyncspeed(Npol,freq=60,Hz=False,rpm=False):# noqa: D401 "Synchronous" is an intentional descriptorr""" Synchronous Speed Calculator Function. Simple method of calculating the synchronous speed of an induction machine given the number of poles in the machine's construction, and the machine's operating electrical frequency. .. math:: \omega_{\text{syn}}=\frac{2\pi \cdot\text{freq}}{\frac{N_{\text{pol}}}{2}} Parameters ---------- Npol: int Number of electrical poles in machine's construction. freq: float, optional Frequency of electrical system in Hertz, default=60 Hz: bool, optional Boolean control to enable return in Hertz. default=False rpm: bool, optional Boolean control to enable return in rpm. default=False Returns ------- wsyn: float Synchronous Speed of Induction Machine, defaults to units of rad/sec, but may be set to Hertz or RPM if `Hz` or `rpm` set to True. """ifNpol==0:raiseZeroDivisionError("Poles of an electrical machine \ can not be zero")wsyn=2*_np.pi*freq/(Npol/2)ifHz:return(2*freq/(Npol))ifrpm:return(120*freq)/(Npol)returnwsyn
# Define Machine Slip Calculation Function
[docs]defmachslip(mech,syn=60):r""" Machine Slip Calculator. Given the two parameters (mechanical and synchronous speed, or frequency) this function will return the unitless slip of the rotating machine. .. math:: \text{slip}=\frac{\text{syn}-\text{mech}} {\text{syn}} Parameters ---------- mech: float The mechanical frequency (or speed), of the rotating machine. syn: float, optional The synchronous frequency (or speed), defaults as a frequency set to 60Hz, default=60 Returns ------- slip: float The rotating machine's slip constant. """slip=(syn-mech)/synreturnslip
# Define 3-Phase Valpha Calculator
[docs]defphs3valpha(VA,VB=0,VC=0):r""" Three-Phase V-Alpha Calculator. Accepts the three-phase voltages for which the accumulated Alpha voltage should be calculated. .. math:: V_{\alpha}=V_A-\frac{V_B}{2}-\frac{V_C}{2} Parameters ---------- VA: [float, complex] A-phase voltage, (or tuple/list of voltages), unitless. VB: [float, complex], optional B-phase voltage, unitless. VC: [float, complex], optional C-phase voltage, unitless. Returns ------- Valpha: [float, complex] Alpha-voltage as calculated from input three-phase voltages. Matches type of inputs. """# Handle Combined (list/tuple) Inputifisinstance(VA,(tuple,list))andVB==0andVC==0:iflen(VA)!=3:raiseValueError("Invalid input set, must ""be list of three elements, three inputs,"" or three array-like objects of equal ""length.")Valpha=VA[0]-VA[1]/2-VA[2]/2# Handle Separated Inputselse:Valpha=VA-VB/2-VC/2# Return the Alpha-VoltagereturnValpha
[docs]defwireresistance(length=None,diameter=None,rho=16.8*10**-9,R=None):r""" Wire Resistance Calculator. Enter three values to calculate the remaing one. Even though every variable is unitless, please use the International System of Units. .. math:: R = \frac{\rho*l}{A} Parameters ---------- length: [float], optional Wire length, unitless diameter: [float], optional Wire diameter, unitless. rho: [float], optional Material resistivity, unitless Default value is copper resistivity: 16.8*10-9 R: [float], optional Wire resistance, unitless. Returns ------- length: [float], optional Wire length, unitless diameter: [float], optional Wire diameter, unitless. rho: [float], optional Material resistivity, unitless Default value is copper resistivity: 16.8*10-9 R: [float], optional Wire resistance, unitless. """ifR==length==diameterisNone:raiseValueError("To few arguments.")# Given length and diameteriflengthisnotNoneanddiameterisnotNone:# calculating the areaA=pi*(diameter**2)/4returnrho*length/A# Given resistance and diameterifRisnotNoneanddiameterisnotNone:# calculating the areaA=pi*(diameter**2)/4returnR*A/rho# Given resistance and lengthifRisnotNoneandlengthisnotNone:A=rho*length/Rreturn_np.sqrt(4*A/pi)
[docs]defparallel_plate_capacitance(A=None,d=None,e=e0,C=None):r""" Parallel-Plate Capacitance Calculator. Enter three values to calculate the remaing one. Even though every variable is unitless, please use the International System of Units. .. math:: C = \frac{\varepsilon \cdot A}{d} Parameters ---------- A: float, optional Area of the plate, unitless. d: float, optional Distance between the plates, unitless. e: float, optional Permitivity of the dielectric, unitless. Default value is the permittivity of free space: 8.854E-12 C: float, optional Capacitance, unitless. Returns ------- A: float, optional Area of the plate, unitless. d: float, optional Distance between the plates, unitless. e: float, optional Permitivity of the dielectric, unitless. Default value is the permittivity of free space: 8.854E-12 C: float, optional Capacitance, unitless. """ifC==A==disNone:raiseValueError("To few arguments.")# Given area and distanceifAisnotNoneanddisnotNone:returne*A/d# Given capacitance and distanceifCisnotNoneanddisnotNone:returnd*C/e# Given capacitance and areaifCisnotNoneandAisnotNone:returne*A/C
[docs]defsolenoid_inductance(A=None,l=None,N=None,u=u0,L=None):r""" Solenoid Inductance Calculator. Enter four values to calculate the remaing one. Even though every variable is unitless, please use the International System of Units. .. math:: L = \frac{\mu \cdot N^2 \cdot A}{l} Parameters ---------- A: float, optional Cross sectional area, unitless. l: float, optional Length, unitless. N: float, optional Number of turns, unitless. u: float, optional Core permeability, unitless. Default value is the permeability of free space: 4πE-7 L: float, optional Inductance, unitless. Returns ------- A: float, optional Cross sectional area, unitless. l: float, optional Length, unitless. N: float, optional Number of turns, unitless. u: float, optional Core permeability, unitless. Default value is the permeability of free space: 4πE-7 L: float, optional Inductance, unitless. """ifL==A==l==NisNone:raiseValueError("To few arguments.")# Given area, length and number of turnsifAisnotNoneandlisnotNoneandNisnotNone:returnN**2*u*A/l# Given inductance, length and number of turnsifLisnotNoneandlisnotNoneandNisnotNone:returnL*l/(N**2*u)# Given inductance, area and number of turnsifLisnotNoneandAisnotNoneandNisnotNone:returnN**2*u*A/L# Given inductance, area and lengthifLisnotNoneandAisnotNoneandlisnotNone:return_np.sqrt(L*l/(u*A))
[docs]defic_555_astable(R=None,C=None,freq=None,t_high=None,t_low=None):""" 555 Integrated Circuit Calculator. Evaluate a number of common attributes related to the common 555 integrated circuit including time period, frequency, duty cycle, time spent low during each cycle, time spent high during each cycle. TODO: This function should be broken into multiple smaller functions. Parameters ---------- R: list[float, float] or tuple(float, float), optional List of 2 resistor which are need in configuring IC 555. C: float, optional Capacitance between Threshold Pin and ground f: float, optional Electrical system frequency in Hertz. t_high: float, optional ON time of IC 555 t_low: float, optional OFF time of IC 555 Returns ------- dict: "time_period": Time period of oscillating IC 555 "frequency": frequency of oscilation of IC 555 "duty_cycle": ration between ON time and total time "t_low": ON time of IC 555 "t_high": OFF time of IC 555 """ifRisnotNoneandCisnotNone:iflen(R)!=2:raiseValueError("Monostable 555 IC will have only 2 resitances to be fixed "f"but {len(R)} were given")[R1,R2]=RT=_np.log(2)*C*(R1+2*R2)freq=1/Tt_low=_np.log(2)*C*R2t_high=_np.log(2)*C*(R1+R2)duty_cycle=t_high*100/Treturn{'time_period':T,'frequency':freq,'duty_cycle':duty_cycle,'t_low':t_low,'t_high':t_high}ift_highisnotNoneandt_lowisnotNoneandCisnotNone:x2=t_low/C*_np.log(2)x1=t_high/C*_np.log(2)T=t_high+t_lowfreq=1/(T)duty_cycle=t_high/(T)return{'time_period':T,'frequency':freq,'duty_cycle':duty_cycle,'R1':x1-x2,'R2':x2}raiseTypeError("Not enough parqmeters are passed")
[docs]defic_555_monostable(R=None,C=None,freq=None,t_high=None,t_low=None):""" 555 Integrated Circuit Calculator. Evaluate a number of common attributes related to the common 555 integrated circuit including time period, frequency, duty cycle, time spent low during each cycle, time spent high during each cycle. TODO: This function should be broken into multiple smaller functions. Parameters ---------- R: list[float, float] or tuple(float, float), optional List of 2 resistor which are need in configuring IC 555. C: float, optional Capacitance between Threshold Pin and ground f: float, optional Electrical system frequency in Hertz. t_high: float, optional ON time of IC 555 t_low: float, optional OFF time of IC 555 Returns ------- dict: "time_period": Time period of oscillating IC 555 "frequency": frequency of oscilation of IC 555 "duty_cycle": ration between ON time and total time "t_low": ON time of IC 555 "t_high": OFF time of IC 555 """T=t_high+t_lowifRisNone:ifnot(CisnotNoneandTisnotNone):raiseValueError("To find Resitance, Capacitance and delay time should be ""provided")returnT/(_np.log(3)*C)ifCisNone:ifnot(RisnotNoneandTisnotNone):raiseValueError("To find Capacitance , Resistance and delay time should be ""provided")returnT/(_np.log(3)*R)ifTisNone:ifnot(RisnotNoneandTisnotNone):raiseValueError("To find Time delay , Resistance and Capacitance should be ""provided")returnR*C*_np.log(3)
[docs]deft_attenuator(Adb,Z0):r""" T attenuator. The T attenuator is a type of attenuator that looks like the letter T. The T attenuator consists of three resistors. Two of these are connected in series and the other one is connected from between the two other resistors to ground. The resistors in series often have the same resistance. .. math:: R1 = Z0*(\frac{10^{\frac{A_{db}}{20}}-1}{10^{\frac{A_{db}}{20}}+1}); .. math:: R2 = Z0*(\frac{10^{\frac{A_{db}}{20}}}{10^{\frac{A_{db}}{10}}-1}) .. image:: /static/t-attenuator-circuit.png Parameters ---------- Adb: float Attenuation in db Z0: float Impedence Returns ------- R1: float T attenuator R1 R2: float T attenuator R2 """x=Adb/20R1=Z0*(_np.power(10,x)-1)/(_np.power(10,x)+1)R2=2*Z0*_np.power(10,x)/(_np.power(10,2*x)-1)returnR1,R2
[docs]defpi_attenuator(Adb,Z0):r""" Pi attenuator. The Pi attenuator is a type of attenuator that looks like the Greek letter π. The Pi attenuator consists of three resistors. One of these is connected in series and the other two are connected in parallel to ground. The parallel resistors often have the same resistance. .. math:: R1 = Z0*(\frac{10^{\frac{A_{db}}{20}}+1}{10^{\frac{A_{db}}{20}}-1}) .. math:: R2 = \frac{Z0}{2}*(10^{\frac{A_{db}}{20}} - \frac{1}{10^{\frac{A_{db}}{20}}}) .. image:: /static/pi-attenuator-circuit.png Parameters ---------- Adb: float Attenuation in db Z0: float Impedence Returns ------- R1: float π attenuator R1 R2: float π attenuator R2 """x=Adb/20R1=Z0*(_np.power(10,x)+1)/(_np.power(10,x)-1)R2=(Z0/2)*(_np.power(10,x)-(1/(_np.power(10,x))))returnR1,R2
# Calculate Zener Diode Resistor
[docs]defzener_diode_required_resistor(Vin,Vo,I):r""" Zener diode required resistance function . A zener diode is uses to allow current to flow "backwards" when the zener voltage is reached. This function use to calculate the required resistor value following below formula: .. math:: R = \frac{V_{in(min)} - V_{out}}{I_{load}+0.01} .. image:: /static/zenerdiode.png Parameters ---------- Vin: float Minimum input Voltage in Volt Vo: float Output Voltage in Volt I: float Load Current in Ampere Returns ------- R: float Load Resistance in Ohm """# Solve Load ResistanceR=(Vin-Vo)/(I+0.01)return(R)
# Calculate Zener Diode Power
[docs]defzener_diode_power(Vin,Vo,R):r""" Zener diode power loss function. A zener diode is uses to allow current to flow "backwards" when the zener voltage is reached. This function use to calculate the power in resistor following below formula: .. math:: P_R = \frac{(V_{out} - V_{in(max)})^2}{R} .. image:: /static/zenerdiode.png Parameters ---------- Vin: float Maximum input Voltage in Volt Vo: float Output Voltage in Volt R: float Load Resistance in Ohm Returns ------- P: float Power on resistance in Watt """# Validate InputsifR==0:raiseValueError("Resistance Value can not be zero")# Solve Load ResistanceP=((Vo-Vin)**2)/Rreturn(P)
[docs]deflm317(r1,r2,v_out):r""" LM317 linear voltage regulator solver. The LM317 is a linear voltage regulator that can be adjusted to supply a specific output voltage. The LM317 has three pins, adjust, output and input. The LM317 is often connected as in the image below. [1]_ .. image:: https://www.basictables.com/media/lm317-circuit.png Formula to Calculate Output Voltage, R1, R2: .. math:: V_{out} = 1.25 * (1+\frac{R2}{R1}) .. math:: R1 = \frac{1.25*R2}{V_{out}-1.25} .. math:: R2 = \frac{R1*V_{out}}{1.25 - R1} Parameters ---------- v_out: float, Optional Output Voltage in LM317 in Volts r1: float, Optional r1 is resistance and is measured in ohm r2: float, Optional r2 is resistance and is measured in ohm Returns ------- v_out: float v_out is the output voltage and is measured in volt (V) r1: float r1 is resistance and is measured in ohm r2: float r2 is resistance and is measured in ohm .. [1] Electronial, "LM317" BasicTables, Accessed May, 2022 https://www.basictables.com/electronics/lm317 """ifr1isnotNoneandr2isnotNone:# Returns Voltagereturn1.25*(1+(r2/r1))ifr2isnotNoneandv_outisnotNone:# Returns R1return(1.25*r2)/(v_out-1.25)ifr1isnotNoneandv_outisnotNone:# Returns R2return((r1*v_out)/1.25)-r1raiseValueError("Invalid arguments")
# Define Module Specific Variables_name_=NAME_version_=VERSION__version__=_version_# Alias Version for User Ease# END OF FILE