Compare commits

...

4 commits

21 changed files with 767 additions and 29 deletions

5
.gitignore vendored
View file

@ -1,7 +1,6 @@
# Python-generated files # Python-generated files
__pycache__/ __pycache__/
*.py[oc] *.py[oc]
build/
dist/ dist/
wheels/ wheels/
*.egg-info *.egg-info
@ -14,6 +13,10 @@ wheels/
uv.lock uv.lock
.python-version .python-version
# docs folders
docs/build/
# MacOS things # MacOS things
.DS_Store* .DS_Store*

View file

@ -2,13 +2,16 @@
or JMKTools for short. or JMKTools for short.
I don't know if this should be called a library or a set of modules. What it is, is a set of functions that replace calculations that I do on a weekly basis. What it is, is a set of functions that replace calculations that I do on a weekly basis.
The library is broken into sections, with more being added later, including circuits and pv. The library is broken into sections, including
Some of these libraries rely on publicly accessible information, including manufacturer data sheets. The libraries that rely on copyrighted information you need to make sure that you have a copy of the standard, code, etc before initializing the software. - general
- circuits
- grounding
- and pv.
Use the example python notebook to get started. Some of these modulesrely on publicly accessible information, including manufacturer data sheets.
## What we're missing ## What we're missing
@ -19,8 +22,15 @@ Tests, I haven't written any real tests for this set of libraries, yet. That wil
Currently the tools use the CEC, in most cases this will match the NEC, but something we are working on is updating that so we can select from which code version should be used for the calculation. Currently the tools use the CEC, in most cases this will match the NEC, but something we are working on is updating that so we can select from which code version should be used for the calculation.
Another limitation is the use of SQL databases. This limits its functionality as a module, but my ability with pandas dataframe lookups is very weak. If anyone wants to make the changes and submit a pull request, we can develop that method on a different branch and test it to the main in the near future.
# Future Features # Future Features
There are a lot of different features that I am planning, including building a web app that will allow this tool to be easily used from a browser, but before I get to that the largest feature that I need to figure out is how to install this as a module so that it can be called from any script that you want. - [x] Web app (this is started at [Digital Power Systems Toolbox](http://toolbox.digitalpowersystems.net)
- [x] Installable package [The first releases are here](https://git.jmkengineering.com/JMK_Engineering_Inc/JMKTools/releases)
- [ ] Add NEC to the calculations
- [x] Re-do and add PV functions to the package.
- [ ] Detailed documentation (the source is started in this repo)
- [ ] Electrical Safety Calculations
- [ ] Basic Load flow tools
- [ ] Basic Short circuit tools
- [ ] Continue developing the DPS Toolbox

20
docs/Makefile Normal file
View file

@ -0,0 +1,20 @@
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = source
BUILDDIR = build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)

35
docs/make.bat Normal file
View file

@ -0,0 +1,35 @@
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=source
set BUILDDIR=build
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.https://www.sphinx-doc.org/
exit /b 1
)
if "%1" == "" goto help
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end
popd

View file

@ -0,0 +1,13 @@
Circuit Functions
================================
.. toctree::
:maxdepth: 2
:caption: Contents:
.. automodule:: jmktools.circuits
:members:

44
docs/source/conf.py Normal file
View file

@ -0,0 +1,44 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# Configure autodoc
import os
import sys
sys.path.insert(0, os.path.abspath('../src/jmktools/'))
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
project = 'JMK Engineering Python Tools'
copyright = '2025, Jeff MacKinnon'
author = 'Jeff MacKinnon'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
extensions = ['sphinx.ext.autodoc',]
templates_path = ['_templates']
exclude_patterns = []
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = "sphinx_book_theme"
html_static_path = ['_static']
html_title = "JMK Engineering Python Tools Documentation"
html_theme_options = {
"repository_url": "https://git.jmkengineering.com/JMK_Engineering_Inc/JMKTools",
"repository_provider": "github",
"use_repository_button": True,
}

View file

@ -0,0 +1,12 @@
General Functions
================================
.. toctree::
:maxdepth: 2
:caption: Contents:
va
.. automodule:: jmktools.general
:members:

View file

@ -0,0 +1,17 @@
va - Volt-Amps
================
.. function:: va(voltage, current, phases=3)
:module: src.jmktools.general
:param voltage: The voltage of the circuit
:type voltage: float
:param current: The current of the circuit
:type current: float
:returns: volt-Amps in VA
:rtype: float
Describe the function

View file

@ -0,0 +1,10 @@
Grounding Functions
================================
.. toctree::
:maxdepth: 2
:caption: Contents:
.. automodule:: jmktools.grounding
:members:

23
docs/source/index.rst Normal file
View file

@ -0,0 +1,23 @@
.. JMK Engineering Python Library documentation master file, created by
sphinx-quickstart on Wed Jan 1 14:10:19 2025.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
JMK Engineering Python Tools Documentation
============================================
This site is the official documentation for `jmktools <https://git.jmkengineering.com/JMK_Engineering_Inc/JMKTools>`_.
The package is broken into various modules to keep the functions "clean". Currently they are
.. toctree::
:maxdepth: 1
:caption: Contents:
installation
general/index
pvsolar/index
circuits/index
grounding/index

View file

@ -0,0 +1,12 @@
Installation
==============
The project releases, complete with release details are found on the `JMK Engineering git site <https://git.jmkengineering.com/JMK_Engineering_Inc/JMKTools/releases>`_. We are also including pypi installable releases `here <https://pypi.org/project/jmktools/>`_.
To install use ``pip install jmktools``. We recommend using `uv <https://docs.astral.sh/uv/>`_ for managing python projects.
Once you have it installed you would use:
``uv init``
``uv add jmktools``

View file

@ -0,0 +1,18 @@
PV Solar Functions
================================
.. toctree::
:maxdepth: 2
:caption: Contents:
voc
.. automodule:: jmktools.pvsolar
:members:

View file

@ -0,0 +1,40 @@
PV Voc Functions
================================
When designing the strings for a PV solar system, the string voltage shall never be higher than the input voltage of the inverter or storage controller. PV panels nameplate voltage is typically shown at the standard testing condition (STC) temperature of 25C. As the outside temperature drops, the open-circuit voltage of the panel will increase.
To ensure that this voltage doesn't over-voltage the connected equipment, we need to use the minimum site temperature, and the :math:`\beta` of the panel. We will assume that it is -0.5 unless you pass a different value.
Temp Adjusted Voc
--------------------
.. function:: temp_adj_Voc(Voc,temp,beta=-0.5,STCtemp = 25)
:no-index:
:module: src.jmktools.pvsolar
:param Voc: The open-circuit voltage of the PV Panel
:type Voc: float
:param temp: The minimum temperature that the panel will be operating.
:type temp: float
:returns: Adjusted Voc in volts
:rtype: float
The Voc of a panel will increase as the temperature decreases.
The datasheet Voc is typically at STC, or 25C. As the temperature decreases this Voc needs to be adjusted.
This adjustment is linear based on the beta value with the units %/C.
This beta value will be shown as a negative indicating that as the temperature increases, then the Voc will decrease.
This Voc decrease results in derating of power during temperature above 25C.
Voc = The STC panel open circuit voltage
temp = The min or max temperature for the PV plant.
beta = The panel temperature coefficient. default -0.5%/C, typical values will range from -0.2 to -0.45.
The adjusted Voc is Voc minus the voltage shift. When the outside temperature is above the STC value then the Vocadj will be lower.

View file

@ -1,13 +1,13 @@
[project] [project]
name = "jmktools" name = "jmktools"
version = "0.1.0" version = "0.2b1"
description = "JMK Engineering Python Toolboox" description = "JMK Engineering Python Toolboox"
readme = "README.md" readme = "README.md"
license = "AGPL-3.0-or-later" license = "AGPL-3.0-or-later"
license-files = [ license-files = [
"LICENSE", "LICENSE",
] ]
requires-python = ">=3.14" requires-python = ">=3.13"
dependencies = [ dependencies = [
"numpy>=2.4.2", "numpy>=2.4.2",
"pandas>=3.0.0", "pandas>=3.0.0",
@ -19,3 +19,9 @@ jmktools = "jmktools:main"
[build-system] [build-system]
requires = ["uv_build>=0.10.0,<0.11.0"] requires = ["uv_build>=0.10.0,<0.11.0"]
build-backend = "uv_build" build-backend = "uv_build"
[dependency-groups]
docs = [
"sphinx>=9.1.0",
"sphinx-book-theme>=1.1.4",
]

View file

@ -228,26 +228,27 @@ cec24table6C = [
] ]
# TODO - Add tables 6D thru 6K # TODO - Add tables 6D thru 6K
# Table 9A/B Internal diameter and cross-sectional areas of various trade conduit and tubing
# Only using the internal diameter (ID) for each of these conduits, along with the trade size. This will be used to calculate the area and fill for the various limits per Table 8
''' '''
rmc = rigid metal conduit Table 9A/B Internal diameter and cross-sectional areas of various trade conduit and tubing
fmc = flexible metal conduit
rpvc = rigid PVC Only using the internal diameter (ID) for each of these conduits, along with the trade size. This will be used to calculate the area and fill for the various limits per Table 8
db2 = rigid Type EB1 PVC and rigid type DB2/ES2 PVC conduit
mlt = metallic liquid tight, flexible conduit - rmc = rigid metal conduit
nmlt = non-metallic liquid tight conduit - fmc = flexible metal conduit
emt = electrical metallic tubing - rpvc = rigid PVC
ent = electrical non-metallic tubing - db2 = rigid Type EB1 PVC and rigid type DB2/ES2 PVC conduit
rtrcips = rigid RTRC conduit marked IPS - mlt = metallic liquid tight, flexible conduit
rtrcid = rigid RTRC conduit marked ID - nmlt = non-metallic liquid tight conduit
sch40 = HDPE conduit schedule 40 - emt = electrical metallic tubing
sch80 = HDPE conduit schedule 80 - ent = electrical non-metallic tubing
dr9 = HDPE DR9 conduit - rtrcips = rigid RTRC conduit marked IPS
dr11 = HDPE DR11 conduit - rtrcid = rigid RTRC conduit marked ID
dr13 = HDPE DR13.5 conduit - sch40 = HDPE conduit schedule 40
dr15 = HDPE DR15.5 conduit - sch80 = HDPE conduit schedule 80
- dr9 = HDPE DR9 conduit
- dr11 = HDPE DR11 conduit
- dr13 = HDPE DR13.5 conduit
- dr15 = HDPE DR15.5 conduit
''' '''
cec24table9AB = [ cec24table9AB = [
['size','RMC', 'FMC', 'RPVC', 'DB2', 'LTMC', 'LTNMC','EMT', 'ENT', 'RTRCIPS', 'RTRCID', 'SCH40', 'SCH80', 'DR9','DR11', 'DR13', 'DR15'], ['size','RMC', 'FMC', 'RPVC', 'DB2', 'LTMC', 'LTNMC','EMT', 'ENT', 'RTRCIPS', 'RTRCID', 'SCH40', 'SCH80', 'DR9','DR11', 'DR13', 'DR15'],

View file

@ -1,5 +1,7 @@
from .circuits import * from .circuits import *
from .general import * from .general import *
from .grounding import *
from .pvsolar import *
from .tables import * from .tables import *
def main() -> None: def main() -> None:

View file

@ -5,7 +5,7 @@ by: Jeff MacKinnon
email: jeff@jmkengineering.com email: jeff@jmkengineering.com
Some General Functions and things Some General Functions and things
----------------------------------
''' '''
import pandas as pd import pandas as pd
import numpy as np import numpy as np

62
src/jmktools/grounding.py Normal file
View file

@ -0,0 +1,62 @@
'''
JMK Engineering Inc. Python Tools
by: Jeff MacKinnon
email: jeff@jmkengineering.com
Grounding functions
'''
import pandas as pd
import math
def resistivity_wenner(spacing,resistance):
'''
This function calculates the resistivity in ohm-m from the wenner resistance measurements.
The spacing must be in meters and the resistance in ohms.
'''
rho = 2 * math.pi * spacing * resistance
return rho
def laurent (area,len_conductor,resistivity):
'''
This function calculates the expected Rg of a grounding system using the Laurent Method, also known as the IEEE 80 Simplified method.
Rg_area = (soil_resistivity / (4 * sqrt(Area_of_grounding_system))
Rg_conductors = soil_resistivity / total_buried_conductor_length
Rg = Rg_area + Rg_conductors
'''
rg_area = resistivity / (4 * math.sqrt(area))
rg_conductor = resistivity / len_conductor
rg = rg_area + rg_conductor
return rg
def sverak(area,len_conductor,depth,resistivity):
'''
This is IEEE 80, Equation 57 or Sverak method to calcuate the Rg.
It is:
Rg = soil_resistivity*[1/total_buried_conductor_length + {(1/sqrt(20*Area_of_grounding_system)) * (1 + 1/(1+buried_depth_grounding_system * sqrt(20 / Area_of_grounding_system)))}]
This function breaks the function into three parts to make it easier to read.
'''
sv_part1 = 1/ len_conductor
sv_part2 = 1 / math.sqrt(20 * area)
sv_part3 = 1 + (1 / (1 + depth * math.sqrt(20 / area)))
rg = resistivity * (sv_part1 + sv_part2 * sv_part3)
return rg

62
src/jmktools/pvsolar.py Normal file
View file

@ -0,0 +1,62 @@
'''
JMK Engineering Inc. Python Tools
by: Jeff MacKinnon
email: jeff@jmkengineering.com
PV Design functions
'''
def temp_adj_Voc(Voc,temp,beta=-0.5,STCtemp = 25):
'''
The Voc of a panel will increase as the temperature decreases.
The datasheet Voc is typically at STC, or 25C. As the temperature decreases this Voc needs to be adjusted.
This adjustment is linear based on the beta value with the units %/C.
This beta value will be shown as a negative indicating that as the temperature increases, then the Voc will decrease.
This Voc decrease results in derating of power during temperature above 25C.
Voc = The STC panel open circuit voltage
temp = The min or max temperature for the PV plant.
beta = The panel temperature coefficient. default -0.5%/C, typical values will range from -0.2 to -0.45.
The adjusted Voc is Voc minus the voltage shift. When the outside temperature is above the STC value then the Vocadj will be lower.
'''
tempadj = STCtemp - temp #-
percent_shift = tempadj * beta/100 #+
volt_shift = Voc * percent_shift
Vocadj = Voc - volt_shift # The voltage adjust is the
return Vocadj
def panels_per_string(Vmax,Voc,beta=-0.5,temp = 25,STCtemp = 25):
'''
This function calculates the maximum number of panels that a string can have.
It will automatically calculate the temperature shifted number when beta and temp are given.
'''
Vocadj = temp_adj_Voc(Voc, temp,beta, STCtemp = 25)
panels_per_string_max = Vmax // Vocadj
return int(panels_per_string_max)
def voltage_per_string(panels,Voc,beta=-0.5,temp = 25,STCtemp = 25):
'''
This function calculates the temperature adjusted string voltage based on the number of panels, open-circuit voltage (Voc).
By default it assumes a beta of -0.5, tem of 25C and a tested STCtemp of 25C.
'''
vocadj = temp_adj_Voc(Voc, temp,beta, STCtemp = 25)
voltage = vocadj * panels
return round(voltage,4)

View file

@ -3,6 +3,8 @@ JMK Engineering Inc. Python Library for design and such.
by: Jeff MacKinnon by: Jeff MacKinnon
email: jeff@jmkengineering.com email: jeff@jmkengineering.com
This module imports all the various tables as shown in the various standards and codes.
''' '''
# #

346
tools.py Normal file
View file

@ -0,0 +1,346 @@
'''
JMK Engineering Inc. Python Library for design and such.
by: Jeff MacKinnon
email: jeff@jmkengineering.com
Commandline tools for JEPL functions
'''
import argparse
import jmktools as jmk
#
# functions for the functions
#
# General
def va(args):
x = [1,3,None]
if args.phases in x:
if args.phases == None:
phases = 3
else:
phases = args.phases
result = jmk.va(args.voltage, args.current, phases=phases)
print ( str(round(result,2))+ "VA")
else:
print(args.phases)
def xfmr_sc(args):
if args.phases == None:
phases = 3
elif arg.phases == 1:
phases = 1
else:
phases = 3
#print(args.kva)
#print(args.voltage)
#print(args.impedance)
result = jmk.xfmr_sc(args.kva, args.voltage, args.impedance, phases = phases)
print(result)
# Circuits
def condsize(args):
if args.temp == None:
temp = 60
else:
temp = args.temp
if args.material == None:
material = 'cu'
else:
material = args.material
if args.code == None:
code = 'CEC'
else:
code = args.code
if args.raceway == None:
raceway = True
elif args.raceway == 'n':
raceway = False
else:
raceway = True
if args.ambient == None:
ambient = 30
else:
ambient = args.ambient
if args.maxsize == None:
maxsize = 500
else:
maxsize = 500
if args.type == None:
loadtype = None
else:
valid_load_type = ['normal','xfmr','xfmrp','xfmrs','motor',None]
if args.type not in valid_load_type:
print(args.type + " is not a valid load_type.")
else:
loadtype = args.type
result = jmk.conductor_size(args.current, temp = temp, material = material, code = code, raceway = raceway, max = maxsize, load_type = loadtype )
print(result)
def condamp(args):
if args.temp == None:
temp = 60
else:
temp = args.temp
if args.material == None:
material = 'cu'
else:
material = args.material
if args.code == None:
code = 'CEC'
else:
code = args.code
if args.raceway == None:
raceway = True
elif args.raceway == 'n':
raceway = False
else:
raceway = True
if args.ambient == None:
ambient = 30
else:
ambient = args.ambient
result = jmk.conductor_ampacity(args.conductor, temp = temp, material = material, code = code, raceway = raceway)
print(result)
def bonding(args):
if args.material == None:
material = 'cu'
else:
material = args.material
if args.code == None:
code = 'CEC'
else:
code = args.code
if args.bus == None:
bus = False
else:
bus = args.bus
result = jmk.bonding_conductor(args.circuit_ampacity, bus = bus, material = material, code = code)
print(result)
def voltagedrop(args):
voltage = args.voltage
current = args.current
size = args.conductor_size
length = args.length
if args.phases == None:
num_phase = 3
elif args.phases == '1':
num_phase = 1
elif args.phases == '3':
num_phase = 3
else:
print('--phase must be 1 or 2.')
if args.material == None:
material = 'cu'
else:
material = args.material
if args.runs == None:
num_runs = 1
else:
num_runs = args.runs
if args.runs == None:
num_runs = 1
else:
num_runs = args.runs
if args.code == None:
code = 'CEC'
else:
code = args.code
if args.powerfactor == None:
power_factor = 'dc'
else:
power_factor = args.powerfactor
if args.raceway == None:
raceway = True
elif args.raceway == 'n':
raceway = False
else:
raceway = True
if args.temp == None:
insul_temp = 75
else:
insul_temp = args.temp
result = jmk.voltage_drop(voltage, current, size, length, num_phase = num_phase, material = material, num_runs = num_runs, code = code, power_factor = power_factor, raceway = raceway, insul_temp = insul_temp)
print(result)
def conduit_size(args):
if args.insulation == None:
insulation = "RW90"
else:
insulation = args.insulation
if args.voltage == None:
voltage = 1000
else:
voltage = args.voltage
if args.jacketed == None:
jacketed = False
else:
jacketed = args.jacketed
if args.material == None:
material = 'SCH80'
else:
material = args.material
if args.code == None:
code = 'CEC'
else:
code = args.code
result = jmk.conduit_size(args.num_conductors,args.size,args.bond,insulation=insulation, voltage = voltage, jacketed = jacketed,material=material, code = code)
percent_fill = str(round(result[3],2) * 100) + "%" + " fill."
print(percent_fill,result[1])
# Solar
def temp_adj_Voc(args):
if args.beta == None:
beta = -0.5
else:
beta = args.beta
if args.stctemp == None:
stctemp = 25
else:
stctemp = args.stctemp
result = jmk.temp_adj_Voc(args.voc, args.temperature, beta, stctemp)
print(str(round(result,2))+"V")
#
# Parse the options
#
try:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(
title="tools",
help="Commandline Functions"
)
#
# This section is for the jepl_general functions
#
# Calcuating VA
va_parser = subparsers.add_parser("va", help="calculate VA (S)")
va_parser.add_argument("voltage", type=float,help="Voltage of the circuit")
va_parser.add_argument("current", type=float,help="Current of the circuit.")
va_parser.add_argument("-p","--phases", type=int,help="Phases of the circuit. It should be either 1 or 3, and we will assume 3 if it is not used.")
va_parser.set_defaults(func=va)
# Calcuating xfmr_sc
xfmrsc_parser = subparsers.add_parser("xfmr_sc", help="Calculates the secondary short circuit current of a transformer")
xfmrsc_parser.add_argument("voltage", type=float,help="Voltage of the circuit")
xfmrsc_parser.add_argument("kva", type=float,help="Transformer rating in kVA.")
xfmrsc_parser.add_argument("impedance", type=float,help="Transformer impedance in percent Z.")
xfmrsc_parser.add_argument("-p","--phases", type=int,help="Phases of the circuit. It should be either 1 or 3, and we will assume 3 if it is not used.")
xfmrsc_parser.set_defaults(func=xfmr_sc)
#
# Circuit Tools
#
condsize_parser = subparsers.add_parser("condsize", help="Determine the conductor size for a defined current and load type.")
condsize_parser.add_argument("current", type=float, help="The current of the circuit.")
condsize_parser.add_argument("-t", "--temp", type=int, help="The temperature rating for the insulation, if none included is 60C. default: 60" )
condsize_parser.add_argument("-m", "--material", type=str, help="This should be cu or al, for copper or aluminum. If none defined cu will be used.")
condsize_parser.add_argument("-c", "--code", type=str, help="Currently this will either be CEC or NEC. default CEC")
condsize_parser.add_argument("-r", "--raceway", type=str, help="If the conductors are in a raceway use y for yes and n for no.")
condsize_parser.add_argument("-a", "--ambient", type=float, help="Ambient temperature in celsious. default: 30")
condsize_parser.add_argument("-x", "--maxsize", type=str, help="Maximum conductor size in AWG/kcmil. default: 500")
condsize_parser.add_argument("--type",type=str, help="Load type {}'normal','xfmr','xfmrp','xfmrs','motor',None}, default: None")
condsize_parser.set_defaults(func=condsize)
condamp_parser = subparsers.add_parser("condamp", help="Determine the ampacity of a conductor.")
condamp_parser.add_argument("conductor", type=str, help="The conductor size in AWG/kcmil")
condamp_parser.add_argument("-t", "--temp", type=int, help="The temperature rating for the insulation, if none included is 60C. default: 60" )
condamp_parser.add_argument("-m", "--material", type=str, help="This should be cu or al, for copper or aluminum. If none defined cu will be used.")
condamp_parser.add_argument("-c", "--code", type=str, help="Currently this will either be CEC or NEC. default CEC")
condamp_parser.add_argument("-r", "--raceway", type=str, help="If the conductors are in a raceway use y for yes and n for no.")
condamp_parser.add_argument("-a", "--ambient", type=float, help="Ambient temperature in celsious. default: 30")
condamp_parser.set_defaults(func=condamp)
bonding_parser = subparsers.add_parser("bonding", help="Bonding conductor for the circuit, wire or bus.")
bonding_parser.add_argument("circuit_ampacity", type=float, help="Circuit ampacity.")
bonding_parser.add_argument("-m", "--material", type=str, help="This should be cu or al, for copper or aluminum. If none defined cu will be used.")
bonding_parser.add_argument("-c", "--code", type=str, help="Currently this will either be CEC or NEC. default CEC")
bonding_parser.add_argument("-b", "--bus", type=bool, help="Bus or wire bond, bus =True, wire = False.")
bonding_parser.set_defaults(func=bonding)
voltagedrop_parser = subparsers.add_parser("voltagedrop", help="Determine the voltage drop of a circuit.")
voltagedrop_parser.add_argument("voltage", type=float, help="The circuit voltage.")
voltagedrop_parser.add_argument("current", type=float, help="The circuit current")
voltagedrop_parser.add_argument("conductor_size", type=str, help="The conductor size.")
voltagedrop_parser.add_argument("length", type=float, help="The circuit length, in metres.")
voltagedrop_parser.add_argument("-t", "--temp", type=int, help="The temperature rating for the insulation, if none included is 60C. default: 75" )
voltagedrop_parser.add_argument("-m", "--material", type=str, help="This should be cu or al, for copper or aluminum. If none defined cu will be used.")
voltagedrop_parser.add_argument("-c", "--code", type=str, help="Currently this will either be CEC or NEC. default CEC")
voltagedrop_parser.add_argument("-r", "--raceway", type=str, help="If the conductors are in a raceway use y for yes and n for no.")
voltagedrop_parser.add_argument("-pf","--powerfactor", type=str, help="Power Factor. Valid options DC, 1, 0.9, 0.8. default dc")
voltagedrop_parser.add_argument("--phases", type=str, help="Number of phases, 1 or 3, default = 3.")
voltagedrop_parser.add_argument("--runs", type=int, help="Number of circuits in parallel, default 1.")
voltagedrop_parser.set_defaults(func=voltagedrop)
consize_parser = subparsers.add_parser("conduitsize", help="Calculate the proper conduit size.")
consize_parser.add_argument("num_conductors", type=int, help="Number of current carrying conductors, typically 1 to 4.")
consize_parser.add_argument("size", type=str, help="Size of the current carrying conductors in AWG or kcmil." )
consize_parser.add_argument("bond", type=str, help="Size of the bond conductor, or equipment grounding conductor in AWG or kcmil")
consize_parser.add_argument("-i", "--insulation", type=str, help="Insulation type. default RW90")
consize_parser.add_argument("-v", "--voltage", type=int, help="Voltage rating of the insulation, 600 or 1000")
consize_parser.add_argument("-j", "--jacketed", type=bool, help="Are the conductors jacketed? Default: False")
consize_parser.add_argument("-m", "--material", type=str, help="Material or conduit type, ie EMT, ENT, SCH40, etc. Default SCH80")
consize_parser.add_argument("-c", "--code", type=str, help="Currently this will either be CEC or NEC. default CEC")
consize_parser.set_defaults(func=conduit_size)
#
# Solar Tools
#
tempvoc = subparsers.add_parser("tempVoc", help="Calculate the temperature adjusted Voc of a PV panel.")
tempvoc.add_argument("voc", type=float,help="Open circuit voltage of the panel.")
tempvoc.add_argument("temperature", type=float, help="Temperature the panel will be at.")
tempvoc.add_argument("-b", "--beta", type=float, help="Panel Beta value, if none is added -0.5 will be used.")
tempvoc.add_argument("-t", "--stctemp", type=float, help="The STC temp. If none is added 25C will be used.")
tempvoc.set_defaults(func=temp_adj_Voc)
# This runs the function that was selected with the arguments in the command.
args = parser.parse_args()
args.func(args)
except argparse.ArgumentError as e:
#log.error("Error parsing arguments")
raise e