From d761cada947f536a4119604f88556580b3dcaeb8 Mon Sep 17 00:00:00 2001 From: Anna Date: Tue, 22 Oct 2019 20:09:03 -0700 Subject: [PATCH 01/20] First iteration of electromagnetic force solenoid model --- models/solenoids/em-force-model.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 models/solenoids/em-force-model.py diff --git a/models/solenoids/em-force-model.py b/models/solenoids/em-force-model.py new file mode 100644 index 00000000..21523e6b --- /dev/null +++ b/models/solenoids/em-force-model.py @@ -0,0 +1,29 @@ +import math; + +#constants + +mu = 4*math.pi*pow(10, -7); +N = 100 #number of coils + + +#Experimental values +Br = 192 +L = 10 #length of solenoid +D = 14 #outer diameter of solenoid. This includes the width of the wires +d = 8 #inner diameter of solenoid +a = 7 #shell casing thickness. This does not include the width of the wires + +#input values +i = 25 #current +zp = 18 #distance to center + +#area calculation (cross section of solenoid) +A = pow((d/2+a), 2)*math.pi + +#outputs + +Bs = ((mu*N*i)*(L+2*zp)*math.log((D+math.sqrt(pow(D, 2)+pow(L+2*zp, 2)))/(d+math.sqrt(pow(d, 2)+pow(L+2*zp, 2)))))/(2*L*(D-d)) + ((mu*N*i)*(L-2*zp)*math.log((D+math.sqrt(pow(D, 2)+pow(L-2*zp, 2)))/(d+math.sqrt(pow(d, 2)+pow(L-2*zp, 2)))))/(2*L*(D-d)) + +a = (mu*N*i)*(L+2*zp)*math.log((D+math.sqrt(pow(D, 2)+pow(L+2*zp, 2)))/(d+math.sqrt(pow(d, 2)+pow(L+2*zp, 2)))) + +print(a) From da6feb9e9fb22befbdcfff8546f0db7af976f2a6 Mon Sep 17 00:00:00 2001 From: Matthew Tong Date: Sat, 26 Oct 2019 14:22:32 -0700 Subject: [PATCH 02/20] Requirements file and MT force model --- .gitignore | 114 ++++++++++++++++++++++++++ models/solenoids/em-force-model-mt.py | 62 ++++++++++++++ models/solenoids/requirements.txt | 1 + 3 files changed, 177 insertions(+) create mode 100644 models/solenoids/em-force-model-mt.py create mode 100644 models/solenoids/requirements.txt diff --git a/.gitignore b/.gitignore index 0c328630..f01b8bf7 100644 --- a/.gitignore +++ b/.gitignore @@ -68,3 +68,117 @@ vhdl/thunderbots_vhdl.prj vhdl/work-obj93.cf vhdl/xlnx_auto_0_xdb vhdl/xst + + +# Created by https://www.gitignore.io/api/venv,pycharm +# Edit at https://www.gitignore.io/?templates=venv,pycharm + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/**/sonarlint/ + +# SonarQube Plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator/ + +### venv ### +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ +pip-selfcheck.json + +# End of https://www.gitignore.io/api/venv,pycharm diff --git a/models/solenoids/em-force-model-mt.py b/models/solenoids/em-force-model-mt.py new file mode 100644 index 00000000..d6c6d471 --- /dev/null +++ b/models/solenoids/em-force-model-mt.py @@ -0,0 +1,62 @@ +import math + +# purpose: Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. However, this does not apply outside the solenoid (at its edges). To find the MF strength at a point outside the body of the solenoid, we use the following program. This value is then used as an input to determine the electromagnetic force. + +#For more information, visit: https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf, or +#http: // spiff.rit.edu / classes / phys313 / lectures / sol / sol_f01_long.html.All variables +#declarationsused in this programare consistent with the links above and categorized into 3 sections: constants. + +# Restricted/Max Values +# length of solenoid +L = 10 +# outer diameter of solenoid. This includes the width of the wires +D = 14 +# inner diameter of solenoid +d = 8 +# shell casing thickness. This does not include the width of the wires +a = 7 + +# constants +# input values +# current +i = 25 +# distance to center +zp = 18 +# number of coils +N = 100 +# area calculation (cross section of solenoid) +A = pow((d / 2 + a), 2) * math.pi + +# permeability constant of free space +mu = 4 * math.pi * pow(10, -7) + +# Calculated values used as inputs +# line current density (current in each wire/length of solenoid)*number of coils +Js = (i / L) * N +# remanent flux density a.k.a remanence +Br = mu * Js + +# outputs + +#outputs: Bsol_z + +constant_multiplier = (mu*N*i)/(2*L) + +differenceOuterInnerSolenoid = D - d + +length_DddDistancefromCenter = L + 2*zp + +length_subtract_distance_from_center = L - 2*zp + +#Used for debugging +ln_termA = (D + math.sqrt(pow(D, 2)+pow(L + 2*zp, 2)))/(d + math.sqrt((pow(d, 2)+pow(L + 2*zp, 2)))) +ln_termB = (D + math.sqrt(pow(D, 2)+pow(L-2*zp, 2)))/(d + math.sqrt(pow(d, 2)+pow(L-2*zp, 2))) + +BsolZ = constant_multiplier/differenceOuterInnerSolenoid*length_addDistancefromCenter*math.log(ln_termA) + constant_multiplier/differenceOuterInnerSolenoid*length_subtractDistancefromCenter*math.log(ln_termB) + + +# force of rod +Fz = (Br * BsolZ * A) / mu + +print(BsolZ) +print(Fz) diff --git a/models/solenoids/requirements.txt b/models/solenoids/requirements.txt new file mode 100644 index 00000000..e9b621ff --- /dev/null +++ b/models/solenoids/requirements.txt @@ -0,0 +1 @@ +numpy==1.17.3 From 4d2e1dbafa66093f21cc1e380eaec393104ed27a Mon Sep 17 00:00:00 2001 From: Anna Date: Tue, 29 Oct 2019 19:34:58 -0700 Subject: [PATCH 03/20] Updated model with camel case --- models/solenoids/em-force-model.py | 66 +++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/models/solenoids/em-force-model.py b/models/solenoids/em-force-model.py index 21523e6b..f9db18ad 100644 --- a/models/solenoids/em-force-model.py +++ b/models/solenoids/em-force-model.py @@ -1,29 +1,57 @@ -import math; +import math -#constants +# Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, +# along the axis to the direction the force is being exerted. +# +# Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. +# However, this does not apply outside the solenoid (at its edges). +# To find the MF strength at a point P outside the body of the solenoid, we use the following program. +# +# P is perpendicular to the cross section of the solenoid. +# This value is then used as an input to determine the electromagnetic force. -mu = 4*math.pi*pow(10, -7); -N = 100 #number of coils +# For more information and referenced diagram (page598), https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf.All +# variables declarations used in this program are categorized into ... +# constants, values to be determined by design, values to be changed during play, output/calculated values +# Constants -#Experimental values -Br = 192 -L = 10 #length of solenoid -D = 14 #outer diameter of solenoid. This includes the width of the wires -d = 8 #inner diameter of solenoid -a = 7 #shell casing thickness. This does not include the width of the wires +mu = 4 * math.pi * pow(10, -7) # permeability constant of free space -#input values -i = 25 #current -zp = 18 #distance to center -#area calculation (cross section of solenoid) -A = pow((d/2+a), 2)*math.pi +# Values determined by design, these being the parameters we can change by changing the design of the solenoid -#outputs +lengthSolenoid = 10 # length of solenoid +outerDiameter = 14 # outer diameter of solenoid. This includes the width of the wires +innerDiameter = 8 # inner diameter of solenoid +shellCasingThickness = 7 # shell casing thickness (the frame we wrap wires around) +distPToCenter = 18 # distance from point P to center +numCoils = 100 # number of coils +crossSectionAreaSolenoid = pow((innerDiameter / 2 + shellCasingThickness), 2) * math.pi +# area calculation (cross section of solenoid) -Bs = ((mu*N*i)*(L+2*zp)*math.log((D+math.sqrt(pow(D, 2)+pow(L+2*zp, 2)))/(d+math.sqrt(pow(d, 2)+pow(L+2*zp, 2)))))/(2*L*(D-d)) + ((mu*N*i)*(L-2*zp)*math.log((D+math.sqrt(pow(D, 2)+pow(L-2*zp, 2)))/(d+math.sqrt(pow(d, 2)+pow(L-2*zp, 2)))))/(2*L*(D-d)) +# input values, these being values we can change during play, when we have finalized design +current = 25 # ### We want to use time as our input -a = (mu*N*i)*(L+2*zp)*math.log((D+math.sqrt(pow(D, 2)+pow(L+2*zp, 2)))/(d+math.sqrt(pow(d, 2)+pow(L+2*zp, 2)))) +# Preliminary Calculations -print(a) +lineCurrentDensity: float = (current / lengthSolenoid) * numCoils # this is used in the calculation for remanence +remanence = mu * lineCurrentDensity # remanent flux density (remanence) + +constantMultiplier = (mu * numCoils * current) / (2 * lengthSolenoid * (outerDiameter - innerDiameter)) +# this calculation for constantMultiplier is for debugging. It is an arbitrary value and have no meaning on its own + + +length_addDistanceFromCenter = lengthSolenoid + 2 * distPToCenter + +length_subtractDistanceFromCenter = lengthSolenoid - 2 * distPToCenter + +# The following are used for debugging purposes. They are arbitrary values and have no meaning in isolation +ln_termA = math.log((outerDiameter + math.sqrt(pow(outerDiameter, 2) + pow(length_addDistanceFromCenter, 2))) / ( + innerDiameter + math.sqrt(pow(innerDiameter, 2) + pow(length_addDistanceFromCenter, 2)))) +ln_termB = math.log((outerDiameter + math.sqrt(pow(outerDiameter, 2) + pow(length_subtractDistanceFromCenter, 2))) / ( + innerDiameter + math.sqrt(pow(innerDiameter, 2) + pow(length_subtractDistanceFromCenter, 2)))) + +fieldStrengthAtP = constantMultiplier / length_addDistanceFromCenter * math.log(ln_termA) \ + + constantMultiplier / length_subtractDistanceFromCenter * math.log(ln_termB) +print(fieldStrengthAtP) From 522dadf3d9e39e06fd3c9219ffb9eaa6280677fa Mon Sep 17 00:00:00 2001 From: Anna Date: Tue, 29 Oct 2019 19:39:42 -0700 Subject: [PATCH 04/20] Removed duplicate file --- models/solenoids/em-force-model-mt.py | 62 --------------------------- 1 file changed, 62 deletions(-) delete mode 100644 models/solenoids/em-force-model-mt.py diff --git a/models/solenoids/em-force-model-mt.py b/models/solenoids/em-force-model-mt.py deleted file mode 100644 index d6c6d471..00000000 --- a/models/solenoids/em-force-model-mt.py +++ /dev/null @@ -1,62 +0,0 @@ -import math - -# purpose: Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. However, this does not apply outside the solenoid (at its edges). To find the MF strength at a point outside the body of the solenoid, we use the following program. This value is then used as an input to determine the electromagnetic force. - -#For more information, visit: https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf, or -#http: // spiff.rit.edu / classes / phys313 / lectures / sol / sol_f01_long.html.All variables -#declarationsused in this programare consistent with the links above and categorized into 3 sections: constants. - -# Restricted/Max Values -# length of solenoid -L = 10 -# outer diameter of solenoid. This includes the width of the wires -D = 14 -# inner diameter of solenoid -d = 8 -# shell casing thickness. This does not include the width of the wires -a = 7 - -# constants -# input values -# current -i = 25 -# distance to center -zp = 18 -# number of coils -N = 100 -# area calculation (cross section of solenoid) -A = pow((d / 2 + a), 2) * math.pi - -# permeability constant of free space -mu = 4 * math.pi * pow(10, -7) - -# Calculated values used as inputs -# line current density (current in each wire/length of solenoid)*number of coils -Js = (i / L) * N -# remanent flux density a.k.a remanence -Br = mu * Js - -# outputs - -#outputs: Bsol_z - -constant_multiplier = (mu*N*i)/(2*L) - -differenceOuterInnerSolenoid = D - d - -length_DddDistancefromCenter = L + 2*zp - -length_subtract_distance_from_center = L - 2*zp - -#Used for debugging -ln_termA = (D + math.sqrt(pow(D, 2)+pow(L + 2*zp, 2)))/(d + math.sqrt((pow(d, 2)+pow(L + 2*zp, 2)))) -ln_termB = (D + math.sqrt(pow(D, 2)+pow(L-2*zp, 2)))/(d + math.sqrt(pow(d, 2)+pow(L-2*zp, 2))) - -BsolZ = constant_multiplier/differenceOuterInnerSolenoid*length_addDistancefromCenter*math.log(ln_termA) + constant_multiplier/differenceOuterInnerSolenoid*length_subtractDistancefromCenter*math.log(ln_termB) - - -# force of rod -Fz = (Br * BsolZ * A) / mu - -print(BsolZ) -print(Fz) From 5d50b79a4113449520caed8ea21c3adc899a785f Mon Sep 17 00:00:00 2001 From: Hannah Sawiuk Date: Wed, 30 Oct 2019 17:26:09 -0700 Subject: [PATCH 05/20] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..dcedc841 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +custom: ['https://crowdfundraising.ubc.ca/projects/ubc-thunderbots/'] From 86e1370a583f28a0939cd8c45ecd82e1c9654339 Mon Sep 17 00:00:00 2001 From: Anna Date: Fri, 1 Nov 2019 15:06:23 -0700 Subject: [PATCH 06/20] added force calculations and changed inputs to be in terms of time --- models/solenoids/em-force-model.py | 33 +++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/models/solenoids/em-force-model.py b/models/solenoids/em-force-model.py index f9db18ad..f4a6e90b 100644 --- a/models/solenoids/em-force-model.py +++ b/models/solenoids/em-force-model.py @@ -17,7 +17,7 @@ # Constants mu = 4 * math.pi * pow(10, -7) # permeability constant of free space - +e = 2.7182818284590452353602874713526624977572470936999 # Values determined by design, these being the parameters we can change by changing the design of the solenoid @@ -30,28 +30,51 @@ crossSectionAreaSolenoid = pow((innerDiameter / 2 + shellCasingThickness), 2) * math.pi # area calculation (cross section of solenoid) +# External Values, changeable, but dependent on other components + +maxVoltage = 4 # the voltage across the capacitor +resistance = 1 # resistance of the device +capacitance = 3 # capacitance of our capacitor + # input values, these being values we can change during play, when we have finalized design -current = 25 # ### We want to use time as our input + +timeElapsed = 4 # ### we want to change length of pulse +directionVector = 1 # Preliminary Calculations +timeConstant = resistance*capacitance + +maxCurrent = maxVoltage/resistance + +current = maxCurrent * pow(e, -timeElapsed/timeConstant) + +print (current) + lineCurrentDensity: float = (current / lengthSolenoid) * numCoils # this is used in the calculation for remanence remanence = mu * lineCurrentDensity # remanent flux density (remanence) -constantMultiplier = (mu * numCoils * current) / (2 * lengthSolenoid * (outerDiameter - innerDiameter)) -# this calculation for constantMultiplier is for debugging. It is an arbitrary value and have no meaning on its own +# The following are used for debugging purposes. They are arbitrary values and have no meaning in isolation +constantMultiplier = (mu * numCoils * current) / (2 * lengthSolenoid * (outerDiameter - innerDiameter)) length_addDistanceFromCenter = lengthSolenoid + 2 * distPToCenter length_subtractDistanceFromCenter = lengthSolenoid - 2 * distPToCenter -# The following are used for debugging purposes. They are arbitrary values and have no meaning in isolation ln_termA = math.log((outerDiameter + math.sqrt(pow(outerDiameter, 2) + pow(length_addDistanceFromCenter, 2))) / ( innerDiameter + math.sqrt(pow(innerDiameter, 2) + pow(length_addDistanceFromCenter, 2)))) ln_termB = math.log((outerDiameter + math.sqrt(pow(outerDiameter, 2) + pow(length_subtractDistanceFromCenter, 2))) / ( innerDiameter + math.sqrt(pow(innerDiameter, 2) + pow(length_subtractDistanceFromCenter, 2)))) +# calculating field strength + fieldStrengthAtP = constantMultiplier / length_addDistanceFromCenter * math.log(ln_termA) \ + constantMultiplier / length_subtractDistanceFromCenter * math.log(ln_termB) print(fieldStrengthAtP) + +# calculating force + +forceOnPiston = fieldStrengthAtP * remanence * crossSectionAreaSolenoid * directionVector / mu # r + +print(forceOnPiston) \ No newline at end of file From d8620a0b0be58d2d1cc4ec2a601ae5a225db3916 Mon Sep 17 00:00:00 2001 From: Hannah Date: Sat, 2 Nov 2019 13:12:46 -0700 Subject: [PATCH 07/20] WIP test file --- models/solenoids/em-force-model.py | 109 +++++++++++++++++------------ models/test_em_force_model.py | 22 ++++++ 2 files changed, 88 insertions(+), 43 deletions(-) create mode 100644 models/test_em_force_model.py diff --git a/models/solenoids/em-force-model.py b/models/solenoids/em-force-model.py index f4a6e90b..fe337e5b 100644 --- a/models/solenoids/em-force-model.py +++ b/models/solenoids/em-force-model.py @@ -1,4 +1,3 @@ -import math # Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, # along the axis to the direction the force is being exerted. @@ -12,69 +11,93 @@ # For more information and referenced diagram (page598), https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf.All # variables declarations used in this program are categorized into ... -# constants, values to be determined by design, values to be changed during play, output/calculated values +# . values to be determined by design, values to be changed during play, output/calculated values +from typing import Dict +import scipy +from scipy import constants -# Constants -mu = 4 * math.pi * pow(10, -7) # permeability constant of free space -e = 2.7182818284590452353602874713526624977572470936999 +# Values determined by design, these being the parameters we can change by +# changing the design of the solenoid -# Values determined by design, these being the parameters we can change by changing the design of the solenoid +def em_force_model(): + + #parameterList: Dict[str, Int] -lengthSolenoid = 10 # length of solenoid -outerDiameter = 14 # outer diameter of solenoid. This includes the width of the wires -innerDiameter = 8 # inner diameter of solenoid -shellCasingThickness = 7 # shell casing thickness (the frame we wrap wires around) -distPToCenter = 18 # distance from point P to center -numCoils = 100 # number of coils -crossSectionAreaSolenoid = pow((innerDiameter / 2 + shellCasingThickness), 2) * math.pi -# area calculation (cross section of solenoid) + length_solenoid = 10 # length of solenoid + outer_diameter = 14 # outer diameter of solenoid. This includes the width of the wires + inner_diameter = 8 # inner diameter of solenoid + # shell casing thickness (the frame we wrap wires around) + shell_casing_thickness = 7 + dist_p__to_center = 18 # distance from point P to center + num_coils = 100 # number of coils + crossSectionArea_solenoid = scipy.power( + (inner_diameter / 2 + shell_casing_thickness), 2) * scipy.pi + # area calculation (cross section of solenoid) -# External Values, changeable, but dependent on other components + # External Values, changeable, but dependent on other components -maxVoltage = 4 # the voltage across the capacitor -resistance = 1 # resistance of the device -capacitance = 3 # capacitance of our capacitor + max_voltage = 4 # the voltage across the capacitor + resistance = 1 # resistance of the device + capacitance = 3 # capacitance of our capacitor -# input values, these being values we can change during play, when we have finalized design + # input values, these being values we can change during play, when we have + # finalized design -timeElapsed = 4 # ### we want to change length of pulse -directionVector = 1 + timeElapsed = 4 # ### we want to change length of pulse + directionVector = 1 -# Preliminary Calculations + # Preliminary Calculations -timeConstant = resistance*capacitance + timeConstant = resistance * capacitance -maxCurrent = maxVoltage/resistance + maxCurrent = max_voltage / resistance -current = maxCurrent * pow(e, -timeElapsed/timeConstant) + current = maxCurrent * scipy.power(scipy.e, -timeElapsed / timeConstant) -print (current) + print(current) -lineCurrentDensity: float = (current / lengthSolenoid) * numCoils # this is used in the calculation for remanence -remanence = mu * lineCurrentDensity # remanent flux density (remanence) + # this is used in the calculation for remanence + lineCurrentDensity: float = (current / length_solenoid) * num_coils + # remanent flux density (remanence) + remanence = constants.mu_0 * lineCurrentDensity -# The following are used for debugging purposes. They are arbitrary values and have no meaning in isolation + # The following are used for debugging purposes. They are arbitrary values + # and have no meaning in isolation -constantMultiplier = (mu * numCoils * current) / (2 * lengthSolenoid * (outerDiameter - innerDiameter)) + constantMultiplier = (constants.mu_0 * num_coils * current) / \ + (2 * length_solenoid * (outer_diameter - inner_diameter)) -length_addDistanceFromCenter = lengthSolenoid + 2 * distPToCenter + length_addDistanceFromCenter = length_solenoid + 2 * dist_p_to_center -length_subtractDistanceFromCenter = lengthSolenoid - 2 * distPToCenter + length_subtractDistanceFromCenter = length_solenoid - 2 * dist_p_to_center -ln_termA = math.log((outerDiameter + math.sqrt(pow(outerDiameter, 2) + pow(length_addDistanceFromCenter, 2))) / ( - innerDiameter + math.sqrt(pow(innerDiameter, 2) + pow(length_addDistanceFromCenter, 2)))) -ln_termB = math.log((outerDiameter + math.sqrt(pow(outerDiameter, 2) + pow(length_subtractDistanceFromCenter, 2))) / ( - innerDiameter + math.sqrt(pow(innerDiameter, 2) + pow(length_subtractDistanceFromCenter, 2)))) + ln_termA = scipy.log((outer_diameter + + scipy.sqrt(scipy.power(outer_diameter, 2) + + scipy.power(length_addDistanceFromCenter, 2))) / + (inner_diameter + + scipy.sqrt(scipy.power(inner_diameter, 2) + + scipy.power(length_addDistanceFromCenter, 2)))) + ln_termB = scipy.log((outer_diameter + + scipy.sqrt(scipy.power(outer_diameter, 2) + + scipy.power(length_subtractDistanceFromCenter, 2))) / + (inner_diameter + + scipy.sqrt(scipy.power(inner_diameter, 2) + + scipy.power(length_subtractDistanceFromCenter, 2)))) -# calculating field strength + # calculating field strength -fieldStrengthAtP = constantMultiplier / length_addDistanceFromCenter * math.log(ln_termA) \ - + constantMultiplier / length_subtractDistanceFromCenter * math.log(ln_termB) -print(fieldStrengthAtP) + fieldStrengthAtP = constantMultiplier / length_addDistanceFromCenter * scipy.log(ln_termA) \ + + constantMultiplier / length_subtractDistanceFromCenter * scipy.log(ln_termB) + print(fieldStrengthAtP) -# calculating force + # calculating force -forceOnPiston = fieldStrengthAtP * remanence * crossSectionAreaSolenoid * directionVector / mu # r + forceOnPiston = fieldStrengthAtP * remanence * \ + crossSectionArea_solenoid * direction_vector / constants.mu_0 # r -print(forceOnPiston) \ No newline at end of file + print(forceOnPiston) + + +if __name__ == "__main__": + em_force_model() diff --git a/models/test_em_force_model.py b/models/test_em_force_model.py new file mode 100644 index 00000000..efff4662 --- /dev/null +++ b/models/test_em_force_model.py @@ -0,0 +1,22 @@ + +from unittest import TestCase +from .em_force_model import em_force_model + +from . + + +class EmForceModelTestCase(TestCase): + def __init__(self, *args): + super(EmForceModelTestCase, self).__init__(*args) + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_flux_outer_diameter(self): + + + + From 7b023b29e0a732a1385dca95cf05cc377f51545d Mon Sep 17 00:00:00 2001 From: JoshuaJSam Date: Sat, 2 Nov 2019 15:48:03 -0700 Subject: [PATCH 08/20] moved everything into individual functions --- .idea/Electrical.iml | 8 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/misc.xml | 7 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + models/solenoids/em-force-model.py | 103 ------------ models/solenoids/em_force_model.py | 157 ++++++++++++++++++ models/solenoids/test_em_force_model.py | 29 ++++ models/test_em_force_model.py | 22 --- 9 files changed, 221 insertions(+), 125 deletions(-) create mode 100644 .idea/Electrical.iml create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml delete mode 100644 models/solenoids/em-force-model.py create mode 100644 models/solenoids/em_force_model.py create mode 100644 models/solenoids/test_em_force_model.py delete mode 100644 models/test_em_force_model.py diff --git a/.idea/Electrical.iml b/.idea/Electrical.iml new file mode 100644 index 00000000..d0876a78 --- /dev/null +++ b/.idea/Electrical.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..86561143 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 00000000..f226b1f2 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..94a25f7f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/models/solenoids/em-force-model.py b/models/solenoids/em-force-model.py deleted file mode 100644 index fe337e5b..00000000 --- a/models/solenoids/em-force-model.py +++ /dev/null @@ -1,103 +0,0 @@ - -# Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, -# along the axis to the direction the force is being exerted. -# -# Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. -# However, this does not apply outside the solenoid (at its edges). -# To find the MF strength at a point P outside the body of the solenoid, we use the following program. -# -# P is perpendicular to the cross section of the solenoid. -# This value is then used as an input to determine the electromagnetic force. - -# For more information and referenced diagram (page598), https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf.All -# variables declarations used in this program are categorized into ... -# . values to be determined by design, values to be changed during play, output/calculated values -from typing import Dict -import scipy -from scipy import constants - - -# Values determined by design, these being the parameters we can change by -# changing the design of the solenoid - -def em_force_model(): - - #parameterList: Dict[str, Int] - - length_solenoid = 10 # length of solenoid - outer_diameter = 14 # outer diameter of solenoid. This includes the width of the wires - inner_diameter = 8 # inner diameter of solenoid - # shell casing thickness (the frame we wrap wires around) - shell_casing_thickness = 7 - dist_p__to_center = 18 # distance from point P to center - num_coils = 100 # number of coils - crossSectionArea_solenoid = scipy.power( - (inner_diameter / 2 + shell_casing_thickness), 2) * scipy.pi - # area calculation (cross section of solenoid) - - # External Values, changeable, but dependent on other components - - max_voltage = 4 # the voltage across the capacitor - resistance = 1 # resistance of the device - capacitance = 3 # capacitance of our capacitor - - # input values, these being values we can change during play, when we have - # finalized design - - timeElapsed = 4 # ### we want to change length of pulse - directionVector = 1 - - # Preliminary Calculations - - timeConstant = resistance * capacitance - - maxCurrent = max_voltage / resistance - - current = maxCurrent * scipy.power(scipy.e, -timeElapsed / timeConstant) - - print(current) - - # this is used in the calculation for remanence - lineCurrentDensity: float = (current / length_solenoid) * num_coils - # remanent flux density (remanence) - remanence = constants.mu_0 * lineCurrentDensity - - # The following are used for debugging purposes. They are arbitrary values - # and have no meaning in isolation - - constantMultiplier = (constants.mu_0 * num_coils * current) / \ - (2 * length_solenoid * (outer_diameter - inner_diameter)) - - length_addDistanceFromCenter = length_solenoid + 2 * dist_p_to_center - - length_subtractDistanceFromCenter = length_solenoid - 2 * dist_p_to_center - - ln_termA = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_addDistanceFromCenter, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_addDistanceFromCenter, 2)))) - ln_termB = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_subtractDistanceFromCenter, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_subtractDistanceFromCenter, 2)))) - - # calculating field strength - - fieldStrengthAtP = constantMultiplier / length_addDistanceFromCenter * scipy.log(ln_termA) \ - + constantMultiplier / length_subtractDistanceFromCenter * scipy.log(ln_termB) - print(fieldStrengthAtP) - - # calculating force - - forceOnPiston = fieldStrengthAtP * remanence * \ - crossSectionArea_solenoid * direction_vector / constants.mu_0 # r - - print(forceOnPiston) - - -if __name__ == "__main__": - em_force_model() diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py new file mode 100644 index 00000000..ee79f6b8 --- /dev/null +++ b/models/solenoids/em_force_model.py @@ -0,0 +1,157 @@ + +# Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, +# along the axis to the direction the force is being exerted. +# +# Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. +# However, this does not apply outside the solenoid (at its edges). +# To find the MF strength at a point P outside the body of the solenoid, we use the following program. +# +# P is perpendicular to the cross section of the solenoid. +# This value is then used as an input to determine the electromagnetic force. + +# For more information and referenced diagram (page598), https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf.All +# variables declarations used in this program are categorized into ... +# . values to be determined by design, values to be changed during play, output/calculated values +from typing import Dict +import scipy +from scipy import constants + + +# Values determined by design, these being the parameters we can change by +# changing the design of the solenoid + +def input_values(): + parameter_list = { + + + } + return parameter_list + + +def em_force_model(parameter_list): + + length_solenoid = 10 # length of solenoid + outer_diameter = 14 # outer diameter of solenoid. This includes the width of the wires + inner_diameter = 8 # inner diameter of solenoid + # shell casing thickness (the frame we wrap wires around) + shell_casing_thickness = 7 + dist_p_to_center = 18 # distance from point P to center + num_coils = 100 # number of coils + cross_section_area_solenoid = scipy.power( + (inner_diameter / 2 + shell_casing_thickness), 2) * scipy.pi + # area calculation (cross section of solenoid) + + # External Values, changeable, but dependent on other components + + max_voltage = 4 # the voltage across the capacitor + resistance = 1 # resistance of the device + capacitance = 3 # capacitance of our capacitor + + # input values, these being values we can change during play, when we have + # finalized design + + time_elapsed = 4 # ### we want to change length of pulse + direction_vector = 1 + + # Preliminary Calculations + + time_constant = resistance * capacitance + + max_current = max_voltage / resistance + + current = max_current * scipy.power(scipy.e, -time_elapsed / time_constant) + + print(current) + + # The following are used for debugging purposes. They are arbitrary values + # and have no meaning in isolation + + # calling calculate_remanence function + remanence = calculate_remanence(current, length_solenoid, num_coils) + + # calling calculate_constant_multiplier function + constant_multiplier = calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, + inner_diameter) + + length_add_distance_from_center = length_solenoid + 2 * dist_p_to_center + + length_subtract_distance_from_center = length_solenoid - 2 * dist_p_to_center + + # calling calculate_ln_term_a function + ln_term_a = calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter) + + # calling calculate_ln_term_b function + ln_term_b = calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter) + + # calling calculating_field_strength function + field_strength_at_p = calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, + ln_term_a, length_subtract_distance_from_center, ln_term_b) + print(field_strength_at_p) + + # calculating force + force_on_piston = calculate_force_on_piston(field_strength_at_p, + remanence, cross_section_area_solenoid, direction_vector) + + print(force_on_piston) + +## + +# FUNCTIONS TO BE CALLED FROM MAIN FUNCTION +# THIS WAS DONE TO REDUCE CLUTTER IN THE MAIN FUNCTION AND TO CREATE LESS COMPLEX UNIT TEST CASES FOR THE FUNCTIONS + +## + + +def calculate_remanence(current, length_solenoid, num_coils): + + # this is used in the calculation for remanence + line_current_density: float = (current / length_solenoid) * num_coils + # remanent flux density (remanence) + remanence = constants.mu_0 * line_current_density + return remanence + + +def calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, inner_diameter): + constant_multiplier = (constants.mu_0 * num_coils * current) / \ + (2 * length_solenoid * (outer_diameter - inner_diameter)) + return constant_multiplier + + +def calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter): + ln_term_a = scipy.log((outer_diameter + + scipy.sqrt(scipy.power(outer_diameter, 2) + + scipy.power(length_add_distance_from_center, 2))) / + (inner_diameter + + scipy.sqrt(scipy.power(inner_diameter, 2) + + scipy.power(length_add_distance_from_center, 2)))) + return ln_term_a + + +def calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter): + ln_term_b = scipy.log((outer_diameter + + scipy.sqrt(scipy.power(outer_diameter, 2) + + scipy.power(length_subtract_distance_from_center, 2))) / + (inner_diameter + + scipy.sqrt(scipy.power(inner_diameter, 2) + + scipy.power(length_subtract_distance_from_center, 2)))) + return ln_term_b + + +def calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, ln_term_a, + length_subtract_distance_from_center, ln_term_b): + + field_strength_at_p = constant_multiplier / length_add_distance_from_center * scipy.log(ln_term_a) \ + + constant_multiplier / length_subtract_distance_from_center * scipy.log(ln_term_b) + return field_strength_at_p + + +def calculate_force_on_piston(field_strength_at_p, remanence, cross_section_area_solenoid, direction_vector): + force_on_piston = field_strength_at_p * remanence * \ + cross_section_area_solenoid * direction_vector / constants.mu_0 + return force_on_piston + +# DEFINING THE input_values FUNCTION AS THE MAIN FUNCTION + + +if __name__ == "__main__": + input_values() diff --git a/models/solenoids/test_em_force_model.py b/models/solenoids/test_em_force_model.py new file mode 100644 index 00000000..a056992f --- /dev/null +++ b/models/solenoids/test_em_force_model.py @@ -0,0 +1,29 @@ + +from unittest import TestCase +from .em_force_model import em_force_model, calculate_remanence + + +class EmForceModelTestCase(TestCase): + def __init__(self, *args): + super(EmForceModelTestCase, self).__init__(*args) + + def setUp(self): + pass + + def tearDown(self): + pass + + def calculate_remanence_test_case(self): + current = 0.1 # Amps + length_solenoid = 10 # + num_turns = 50 # + val = calculate_remanence( + current, + length_solenoid, + num_turns + ) + self.assert(val == 1, "Expected not equal") + + + + diff --git a/models/test_em_force_model.py b/models/test_em_force_model.py deleted file mode 100644 index efff4662..00000000 --- a/models/test_em_force_model.py +++ /dev/null @@ -1,22 +0,0 @@ - -from unittest import TestCase -from .em_force_model import em_force_model - -from . - - -class EmForceModelTestCase(TestCase): - def __init__(self, *args): - super(EmForceModelTestCase, self).__init__(*args) - - def setUp(self): - pass - - def tearDown(self): - pass - - def test_flux_outer_diameter(self): - - - - From 4ee923326ffec823b6f4f3761263247d3dc2d8c0 Mon Sep 17 00:00:00 2001 From: Matthew Tong Date: Sat, 23 Nov 2019 14:22:05 -0800 Subject: [PATCH 09/20] Docstrings Added docstrings to all methods/functions --- .idea/Electrical.iml | 2 +- .idea/misc.xml | 2 +- models/solenoids/em_force_model.py | 84 ++++++++++++++++++++++++- models/solenoids/test_em_force_model.py | 10 +-- 4 files changed, 89 insertions(+), 9 deletions(-) diff --git a/.idea/Electrical.iml b/.idea/Electrical.iml index d0876a78..c98d1518 100644 --- a/.idea/Electrical.iml +++ b/.idea/Electrical.iml @@ -2,7 +2,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 86561143..a8c5713c 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index ee79f6b8..9c542c94 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -30,6 +30,11 @@ def input_values(): def em_force_model(parameter_list): + """ + :param parameter_list: From parameter list, for detailed information look into parameters list and below*** + :return: + """ + length_solenoid = 10 # length of solenoid outer_diameter = 14 # outer diameter of solenoid. This includes the width of the wires inner_diameter = 8 # inner diameter of solenoid @@ -103,21 +108,58 @@ def em_force_model(parameter_list): def calculate_remanence(current, length_solenoid, num_coils): + """ + + Note: reference of physical aspects of parameters can be visualized and view on a diagram in research paper. + Since we split a lot of the many terms, the descriptions will need to be referred back to research paper of + equations for more clarification. + + :param current: + Current that is flowing through the wire + :param length_solenoid: + Length of the physical solenoid + :param num_coils: + Number of turns of coil + :return: + """ # this is used in the calculation for remanence line_current_density: float = (current / length_solenoid) * num_coils # remanent flux density (remanence) - remanence = constants.mu_0 * line_current_density - return remanence + return constants.mu_0 * line_current_density def calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, inner_diameter): + """ + :param num_coils: + Number of turns of coil + :param current: + Current that is flowing through the wire + :param length_solenoid: + Length of the physical solenoid + :param outer_diameter: + Outer diameter of the physical solenoid + :param inner_diameter: + Inner diameter of the physical solenoid + :return: + """ + constant_multiplier = (constants.mu_0 * num_coils * current) / \ (2 * length_solenoid * (outer_diameter - inner_diameter)) return constant_multiplier def calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter): + """ + :param outer_diameter: + Outer diameter of the physical solenoid + :param length_add_distance_from_center: + Length_add_distance_from center term in equation in research paper + :param inner_diameter: + Inner diameter of the physical solenoid + :return: + """ + ln_term_a = scipy.log((outer_diameter + scipy.sqrt(scipy.power(outer_diameter, 2) + scipy.power(length_add_distance_from_center, 2))) / @@ -128,6 +170,16 @@ def calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_d def calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter): + """ + :param outer_diameter: + Outer diameter of the physical solenoid + :param length_subtract_distance_from_center: + Length_subtract_distance_from center term in equation in research paper + :param inner_diameter: + Inner diameter of the physical solenoid + :return: + """ + ln_term_b = scipy.log((outer_diameter + scipy.sqrt(scipy.power(outer_diameter, 2) + scipy.power(length_subtract_distance_from_center, 2))) / @@ -140,12 +192,40 @@ def calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, in def calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, ln_term_a, length_subtract_distance_from_center, ln_term_b): + """ + :param constant_multiplier: + Constant term in the beginning of equation in research paper + :param length_add_distance_from_center: + Length_add_distance_from center term in equation in research paper + :param ln_term_a: + Ln term a in equation reference in research paper + :param length_subtract_distance_from_center: + Length_subtract_distance_from center term in equation in research paper + :param ln_term_b: + Ln term b in equation reference in research paper + :return: + """ + field_strength_at_p = constant_multiplier / length_add_distance_from_center * scipy.log(ln_term_a) \ + constant_multiplier / length_subtract_distance_from_center * scipy.log(ln_term_b) return field_strength_at_p def calculate_force_on_piston(field_strength_at_p, remanence, cross_section_area_solenoid, direction_vector): + + """ + + :param field_strength_at_p: + Strength of magnetic field at point P on the medal kicking bar + :param remanence: + Value of ramanence + :param cross_section_area_solenoid: + The cross sectional area of the solenoid + :param direction_vector: + The directional vector in the direction the force is goign + :return: + """ + force_on_piston = field_strength_at_p * remanence * \ cross_section_area_solenoid * direction_vector / constants.mu_0 return force_on_piston diff --git a/models/solenoids/test_em_force_model.py b/models/solenoids/test_em_force_model.py index a056992f..3c71f930 100644 --- a/models/solenoids/test_em_force_model.py +++ b/models/solenoids/test_em_force_model.py @@ -13,16 +13,16 @@ def setUp(self): def tearDown(self): pass - def calculate_remanence_test_case(self): - current = 0.1 # Amps - length_solenoid = 10 # - num_turns = 50 # + def test_calculate_remanence_test_case(self): + current = 0.1 # Amps + length_solenoid = 10 # + num_turns = 50 # val = calculate_remanence( current, length_solenoid, num_turns ) - self.assert(val == 1, "Expected not equal") + self.assertNotEqual(val, 1, "Expected not equal") From b2e909b25bf6c629d0867350640e4c902fe8e429 Mon Sep 17 00:00:00 2001 From: Anna Date: Sun, 22 Dec 2019 22:30:28 -0800 Subject: [PATCH 10/20] is this how i use git idk --- models/solenoids/em_force_model.py | 155 +++++++++++++++++------------ 1 file changed, 90 insertions(+), 65 deletions(-) diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index ee79f6b8..2415a0f0 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -1,4 +1,3 @@ - # Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, # along the axis to the direction the force is being exerted. # @@ -15,6 +14,8 @@ from typing import Dict import scipy from scipy import constants +import matplotlib.pyplot as plt +import numpy as np # Values determined by design, these being the parameters we can change by @@ -22,77 +23,102 @@ def input_values(): parameter_list = { + 'length_solenoid': 10, # length of solenoid + 'outer_diameter': 14, # outer diameter of solenoid. This includes the width of the wires + 'inner_diameter': 8, # inner diameter of solenoid + # shell casing thickness (the frame we wrap wires around) + 'shell_casing_thickness': 7, + 'dist_p_to_center': 18, # distance from point P to center + 'num_coils': 100, # number of coils + + # External Values, changeable, but dependent on other components + + 'max_voltage': 4, # the voltage across the capacitor + 'resistance': 1, # resistance of the device + 'capacitance': 3, # capacitance of our capacitor + + # input values, these being values we can change during play, when we have + # finalized design + 'total_time': 5., # the time frame we wish to look at + 'time_interval': 0.2, # ### we want to change length of pulse + 'direction_vector': 1, } return parameter_list def em_force_model(parameter_list): - - length_solenoid = 10 # length of solenoid - outer_diameter = 14 # outer diameter of solenoid. This includes the width of the wires - inner_diameter = 8 # inner diameter of solenoid - # shell casing thickness (the frame we wrap wires around) - shell_casing_thickness = 7 - dist_p_to_center = 18 # distance from point P to center - num_coils = 100 # number of coils + # Preliminary Calculations cross_section_area_solenoid = scipy.power( - (inner_diameter / 2 + shell_casing_thickness), 2) * scipy.pi + (parameter_list['inner_diameter'] / 2 + parameter_list['shell_casing_thickness']), 2) * scipy.pi, # area calculation (cross section of solenoid) + time_constant = parameter_list['resistance'] * parameter_list['capacitance'] - # External Values, changeable, but dependent on other components - - max_voltage = 4 # the voltage across the capacitor - resistance = 1 # resistance of the device - capacitance = 3 # capacitance of our capacitor - - # input values, these being values we can change during play, when we have - # finalized design - - time_elapsed = 4 # ### we want to change length of pulse - direction_vector = 1 - - # Preliminary Calculations - - time_constant = resistance * capacitance - - max_current = max_voltage / resistance + max_current = parameter_list['max_voltage'] / parameter_list['resistance'] - current = max_current * scipy.power(scipy.e, -time_elapsed / time_constant) + # The following are used for debugging purposes. They are arbitrary values and have no meaning in isolation - print(current) - - # The following are used for debugging purposes. They are arbitrary values - # and have no meaning in isolation + # for i in range(0, parameter_list['total_time']): + # current_at_t.append(current(max_current, time_elapsed, time_constant)) + # i+time_elapsed # calling calculate_remanence function - remanence = calculate_remanence(current, length_solenoid, num_coils) + # remanence = calculate_remanence(current, parameter_list['length_solenoid'], parameter_list['num_coils']) # calling calculate_constant_multiplier function - constant_multiplier = calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, - inner_diameter) + # constant_multiplier = calculate_constant_multiplier(parameter_list['num_coils'], current, + # parameter_list['length_solenoid'], + # parameter_list['outer_diameter'], + # parameter_list['inner_diameter']) - length_add_distance_from_center = length_solenoid + 2 * dist_p_to_center + length_add_distance_from_center = parameter_list['length_solenoid'] + 2 * parameter_list['dist_p_to_center'] - length_subtract_distance_from_center = length_solenoid - 2 * dist_p_to_center + length_subtract_distance_from_center = parameter_list['length_solenoid'] - 2 * parameter_list['dist_p_to_center'] # calling calculate_ln_term_a function - ln_term_a = calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter) + ln_term_a = calculate_ln_term_a(parameter_list['outer_diameter'], length_add_distance_from_center, + parameter_list['inner_diameter']) # calling calculate_ln_term_b function - ln_term_b = calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter) + ln_term_b = calculate_ln_term_b(parameter_list['outer_diameter'], + length_subtract_distance_from_center, + parameter_list['inner_diameter']) # calling calculating_field_strength function - field_strength_at_p = calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, - ln_term_a, length_subtract_distance_from_center, ln_term_b) - print(field_strength_at_p) + # field_strength_at_p = calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, + # ln_term_a, length_subtract_distance_from_center, ln_term_b) + + # print(field_strength_at_p) # calculating force - force_on_piston = calculate_force_on_piston(field_strength_at_p, - remanence, cross_section_area_solenoid, direction_vector) + # force_on_piston = calculate_force_on_piston(field_strength_at_p, + # remanence, cross_section_area_solenoid, + # parameter_list['direction_vector']) + + # print(force_on_piston) + + time_elapsed = np.arange(0., parameter_list['total_time'], parameter_list['time_interval']) + + # plt.plot(time_elapsed, current(max_current, time_elapsed, time_constant), 'b--') + + plt.plot(time_elapsed, calculate_field_strength_at_p(calculate_constant_multiplier(parameter_list['num_coils'], + current(max_current, + time_elapsed, + time_constant), + parameter_list[ + 'length_solenoid'], + parameter_list['outer_diameter'], + parameter_list[ + 'inner_diameter']), + length_add_distance_from_center, + ln_term_a, + length_subtract_distance_from_center, + ln_term_b), + 'b--') + + plt.show() - print(force_on_piston) ## @@ -101,19 +127,20 @@ def em_force_model(parameter_list): ## +def current(max_current, time_elapsed, time_constant): + cur = max_current * scipy.power(scipy.e, -time_elapsed / time_constant) + return cur -def calculate_remanence(current, length_solenoid, num_coils): - # this is used in the calculation for remanence - line_current_density: float = (current / length_solenoid) * num_coils +def calculate_remanence(current_at_t, length_solenoid, num_coils): # remanent flux density (remanence) - remanence = constants.mu_0 * line_current_density - return remanence + rem = constants.mu_0 * current_at_t / length_solenoid * num_coils + return rem -def calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, inner_diameter): - constant_multiplier = (constants.mu_0 * num_coils * current) / \ - (2 * length_solenoid * (outer_diameter - inner_diameter)) +def calculate_constant_multiplier(num_coils, current_at_t, length_solenoid, outer_diameter, inner_diameter): + constant_multiplier = (constants.mu_0 * num_coils * current_at_t) / \ + (2 * length_solenoid * (outer_diameter - inner_diameter)) return constant_multiplier @@ -129,29 +156,27 @@ def calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_d def calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter): ln_term_b = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_subtract_distance_from_center, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_subtract_distance_from_center, 2)))) + scipy.sqrt(scipy.power(outer_diameter, 2) + + scipy.power(length_subtract_distance_from_center, 2))) / + (inner_diameter + + scipy.sqrt(scipy.power(inner_diameter, 2) + + scipy.power(length_subtract_distance_from_center, 2)))) return ln_term_b def calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, ln_term_a, length_subtract_distance_from_center, ln_term_b): - field_strength_at_p = constant_multiplier / length_add_distance_from_center * scipy.log(ln_term_a) \ - + constant_multiplier / length_subtract_distance_from_center * scipy.log(ln_term_b) + + constant_multiplier / length_subtract_distance_from_center * scipy.log(ln_term_b) return field_strength_at_p def calculate_force_on_piston(field_strength_at_p, remanence, cross_section_area_solenoid, direction_vector): force_on_piston = field_strength_at_p * remanence * \ - cross_section_area_solenoid * direction_vector / constants.mu_0 + cross_section_area_solenoid * direction_vector / constants.mu_0 return force_on_piston -# DEFINING THE input_values FUNCTION AS THE MAIN FUNCTION - -if __name__ == "__main__": - input_values() +# if __name__ == "__main__": +# input_values() +em_force_model(input_values()) From e0ffc0482667ba7c25339d39953c5984a96b5ec8 Mon Sep 17 00:00:00 2001 From: Anna Date: Sun, 22 Dec 2019 22:41:02 -0800 Subject: [PATCH 11/20] gui --- models/solenoids/.idea/.idea/.idea.iml | 8 ++ .../inspectionProfiles/profiles_settings.xml | 6 + models/solenoids/.idea/.idea/misc.xml | 4 + models/solenoids/.idea/.idea/modules.xml | 8 ++ models/solenoids/.idea/.idea/workspace.xml | 4 + .../inspectionProfiles/profiles_settings.xml | 6 + models/solenoids/.idea/misc.xml | 4 + models/solenoids/.idea/modules.xml | 8 ++ models/solenoids/.idea/solenoids.iml | 11 ++ models/solenoids/.idea/vcs.xml | 6 + models/solenoids/.idea/workspace.xml | 132 ++++++++++++++++++ models/solenoids/test_em_force_model.py | 9 +- 12 files changed, 200 insertions(+), 6 deletions(-) create mode 100644 models/solenoids/.idea/.idea/.idea.iml create mode 100644 models/solenoids/.idea/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 models/solenoids/.idea/.idea/misc.xml create mode 100644 models/solenoids/.idea/.idea/modules.xml create mode 100644 models/solenoids/.idea/.idea/workspace.xml create mode 100644 models/solenoids/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 models/solenoids/.idea/misc.xml create mode 100644 models/solenoids/.idea/modules.xml create mode 100644 models/solenoids/.idea/solenoids.iml create mode 100644 models/solenoids/.idea/vcs.xml create mode 100644 models/solenoids/.idea/workspace.xml diff --git a/models/solenoids/.idea/.idea/.idea.iml b/models/solenoids/.idea/.idea/.idea.iml new file mode 100644 index 00000000..d0876a78 --- /dev/null +++ b/models/solenoids/.idea/.idea/.idea.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/.idea/inspectionProfiles/profiles_settings.xml b/models/solenoids/.idea/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/models/solenoids/.idea/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/.idea/misc.xml b/models/solenoids/.idea/.idea/misc.xml new file mode 100644 index 00000000..a2e120dc --- /dev/null +++ b/models/solenoids/.idea/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/.idea/modules.xml b/models/solenoids/.idea/.idea/modules.xml new file mode 100644 index 00000000..08f54a6d --- /dev/null +++ b/models/solenoids/.idea/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/.idea/workspace.xml b/models/solenoids/.idea/.idea/workspace.xml new file mode 100644 index 00000000..6b59c0d1 --- /dev/null +++ b/models/solenoids/.idea/.idea/workspace.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/inspectionProfiles/profiles_settings.xml b/models/solenoids/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/models/solenoids/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/misc.xml b/models/solenoids/.idea/misc.xml new file mode 100644 index 00000000..a2e120dc --- /dev/null +++ b/models/solenoids/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/modules.xml b/models/solenoids/.idea/modules.xml new file mode 100644 index 00000000..aab61eee --- /dev/null +++ b/models/solenoids/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/solenoids.iml b/models/solenoids/.idea/solenoids.iml new file mode 100644 index 00000000..67116063 --- /dev/null +++ b/models/solenoids/.idea/solenoids.iml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/vcs.xml b/models/solenoids/.idea/vcs.xml new file mode 100644 index 00000000..b2bdec2d --- /dev/null +++ b/models/solenoids/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/models/solenoids/.idea/workspace.xml b/models/solenoids/.idea/workspace.xml new file mode 100644 index 00000000..c7d6e89d --- /dev/null +++ b/models/solenoids/.idea/workspace.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1573194861344 + + + + + + + \ No newline at end of file diff --git a/models/solenoids/test_em_force_model.py b/models/solenoids/test_em_force_model.py index a056992f..025da094 100644 --- a/models/solenoids/test_em_force_model.py +++ b/models/solenoids/test_em_force_model.py @@ -1,4 +1,3 @@ - from unittest import TestCase from .em_force_model import em_force_model, calculate_remanence @@ -13,7 +12,7 @@ def setUp(self): def tearDown(self): pass - def calculate_remanence_test_case(self): + def test_calculate_remanence(self): current = 0.1 # Amps length_solenoid = 10 # num_turns = 50 # @@ -22,8 +21,6 @@ def calculate_remanence_test_case(self): length_solenoid, num_turns ) - self.assert(val == 1, "Expected not equal") - - - + self.assertEqual(val, 1, "Expected not equal") + def test_ \ No newline at end of file From 80b8ad47832d92e30efeadf1590b094c3364aa60 Mon Sep 17 00:00:00 2001 From: Anna Date: Sun, 22 Dec 2019 22:53:38 -0800 Subject: [PATCH 12/20] testing out features of tkinter, saving before i screw this up --- models/solenoids/GUIscratch.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 models/solenoids/GUIscratch.py diff --git a/models/solenoids/GUIscratch.py b/models/solenoids/GUIscratch.py new file mode 100644 index 00000000..ce013625 --- /dev/null +++ b/models/solenoids/GUIscratch.py @@ -0,0 +1 @@ +hello From 039045bd4c4db88822e04afc296034b8e7ce3775 Mon Sep 17 00:00:00 2001 From: Anna Date: Mon, 30 Dec 2019 15:37:28 -0800 Subject: [PATCH 13/20] added circle, square, rectangle --- models/solenoids/em_force_model.py | 159 ++++++++++------------------- 1 file changed, 52 insertions(+), 107 deletions(-) diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index 2415a0f0..8550a498 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -1,16 +1,10 @@ -# Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, -# along the axis to the direction the force is being exerted. -# -# Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. -# However, this does not apply outside the solenoid (at its edges). -# To find the MF strength at a point P outside the body of the solenoid, we use the following program. -# -# P is perpendicular to the cross section of the solenoid. +# Purpose: Calculating the magnetic field strength at the center of the solenoid using Biot Savart Law # This value is then used as an input to determine the electromagnetic force. +# For more information refer to 'Solenoid Research' (google docs) -# For more information and referenced diagram (page598), https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf.All # variables declarations used in this program are categorized into ... -# . values to be determined by design, values to be changed during play, output/calculated values +# values to be determined by design, values to be changed during play, output/calculated values + from typing import Dict import scipy from scipy import constants @@ -18,18 +12,13 @@ import numpy as np -# Values determined by design, these being the parameters we can change by -# changing the design of the solenoid - def input_values(): parameter_list = { 'length_solenoid': 10, # length of solenoid - 'outer_diameter': 14, # outer diameter of solenoid. This includes the width of the wires - 'inner_diameter': 8, # inner diameter of solenoid - # shell casing thickness (the frame we wrap wires around) - 'shell_casing_thickness': 7, - 'dist_p_to_center': 18, # distance from point P to center - 'num_coils': 100, # number of coils + 'wire_gauge': 1, # wire gauge + 'diameter': 1, # diameter of circular, side length of square + 'side_long': 2, # longer side for rect, longer value for ellipse + 'side_short': 1, # shorter side for rect, shorter value for ellipse # External Values, changeable, but dependent on other components @@ -37,68 +26,70 @@ def input_values(): 'resistance': 1, # resistance of the device 'capacitance': 3, # capacitance of our capacitor - # input values, these being values we can change during play, when we have - # finalized design + # input values, changes to model (visually) 'total_time': 5., # the time frame we wish to look at 'time_interval': 0.2, # ### we want to change length of pulse - 'direction_vector': 1, - } return parameter_list -def em_force_model(parameter_list): - # Preliminary Calculations - cross_section_area_solenoid = scipy.power( - (parameter_list['inner_diameter'] / 2 + parameter_list['shell_casing_thickness']), 2) * scipy.pi, - # area calculation (cross section of solenoid) - time_constant = parameter_list['resistance'] * parameter_list['capacitance'] +def time_constant(resistance, capaciatance): + tc = resistance * capaciatance + return tc - max_current = parameter_list['max_voltage'] / parameter_list['resistance'] - - # The following are used for debugging purposes. They are arbitrary values and have no meaning in isolation +def max_current(max_voltage, resistance): + mc = max_voltage / resistance + return mc # for i in range(0, parameter_list['total_time']): # current_at_t.append(current(max_current, time_elapsed, time_constant)) # i+time_elapsed - # calling calculate_remanence function - # remanence = calculate_remanence(current, parameter_list['length_solenoid'], parameter_list['num_coils']) - # calling calculate_constant_multiplier function - # constant_multiplier = calculate_constant_multiplier(parameter_list['num_coils'], current, - # parameter_list['length_solenoid'], - # parameter_list['outer_diameter'], - # parameter_list['inner_diameter']) +def calc_mf_circular_solenoid(num_loops, current, diameter): + magnetic_field = scipy.mu_0 * num_loops * current / diameter + return magnetic_field + + +def cross_section_area_circle(dia): # area calculation (cross section of solenoid) + area = scipy.power((dia / 2), 2) * scipy.pi + return area - length_add_distance_from_center = parameter_list['length_solenoid'] + 2 * parameter_list['dist_p_to_center'] - length_subtract_distance_from_center = parameter_list['length_solenoid'] - 2 * parameter_list['dist_p_to_center'] +def calc_mf_square_solenoid(num_loops, current, side_length): + magnetic_field = np.sqrt(2) * scipy.mu_0 * num_loops * current / (scipy.pi * side_length / 2) + return magnetic_field - # calling calculate_ln_term_a function - ln_term_a = calculate_ln_term_a(parameter_list['outer_diameter'], length_add_distance_from_center, - parameter_list['inner_diameter']) - # calling calculate_ln_term_b function - ln_term_b = calculate_ln_term_b(parameter_list['outer_diameter'], - length_subtract_distance_from_center, - parameter_list['inner_diameter']) +def cross_section_area_square(side_length): # area calculation (cross section of solenoid) + area = side_length * side_length + return area - # calling calculating_field_strength function - # field_strength_at_p = calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, - # ln_term_a, length_subtract_distance_from_center, ln_term_b) - # print(field_strength_at_p) +def calc_mf_rect_solenoid(num_loops, current, length_short, length_long): + magnetic_field = (2 * scipy.mu_0 * num_loops * current / scipy.pi) * ( + length_long / (length_short * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2))) + length_short / + (length_long * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2)))) + return magnetic_field - # calculating force - # force_on_piston = calculate_force_on_piston(field_strength_at_p, - # remanence, cross_section_area_solenoid, - # parameter_list['direction_vector']) - # print(force_on_piston) +def cross_section_area_rect(length_long, length_short): # area calculation (cross section of solenoid) + area = length_short * length_long + return area - time_elapsed = np.arange(0., parameter_list['total_time'], parameter_list['time_interval']) + +def calc_mf_oval_solenoid(num_loops, current, length_short, length_long): # ****needs work + magnetic_field = 1 + return magnetic_field + + +def calc_force(area, mf): + force = area * scipy.pow(mf, 2) / 2 / scipy.mu_0 + return force + + +'''# time_elapsed = np.arange(0., parameter_list['total_time'], parameter_list['time_interval']) # plt.plot(time_elapsed, current(max_current, time_elapsed, time_constant), 'b--') @@ -117,8 +108,7 @@ def em_force_model(parameter_list): ln_term_b), 'b--') - plt.show() - + plt.show()''' ## @@ -127,56 +117,11 @@ def em_force_model(parameter_list): ## -def current(max_current, time_elapsed, time_constant): +'''def current(max_current, time_elapsed, time_constant): cur = max_current * scipy.power(scipy.e, -time_elapsed / time_constant) return cur - -def calculate_remanence(current_at_t, length_solenoid, num_coils): - # remanent flux density (remanence) - rem = constants.mu_0 * current_at_t / length_solenoid * num_coils - return rem - - -def calculate_constant_multiplier(num_coils, current_at_t, length_solenoid, outer_diameter, inner_diameter): - constant_multiplier = (constants.mu_0 * num_coils * current_at_t) / \ - (2 * length_solenoid * (outer_diameter - inner_diameter)) - return constant_multiplier - - -def calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter): - ln_term_a = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_add_distance_from_center, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_add_distance_from_center, 2)))) - return ln_term_a - - -def calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter): - ln_term_b = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_subtract_distance_from_center, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_subtract_distance_from_center, 2)))) - return ln_term_b - - -def calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, ln_term_a, - length_subtract_distance_from_center, ln_term_b): - field_strength_at_p = constant_multiplier / length_add_distance_from_center * scipy.log(ln_term_a) \ - + constant_multiplier / length_subtract_distance_from_center * scipy.log(ln_term_b) - return field_strength_at_p - - -def calculate_force_on_piston(field_strength_at_p, remanence, cross_section_area_solenoid, direction_vector): - force_on_piston = field_strength_at_p * remanence * \ - cross_section_area_solenoid * direction_vector / constants.mu_0 - return force_on_piston - +''' # if __name__ == "__main__": # input_values() -em_force_model(input_values()) From 75e67c4e89115be808d0af6b177f8c2c438cd94d Mon Sep 17 00:00:00 2001 From: Anna Date: Mon, 30 Dec 2019 16:51:16 -0800 Subject: [PATCH 14/20] fixed a constant --- models/solenoids/em_force_model.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index 8550a498..9f528155 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -6,11 +6,14 @@ # values to be determined by design, values to be changed during play, output/calculated values from typing import Dict + import scipy from scipy import constants import matplotlib.pyplot as plt import numpy as np +__all__ = [constants] + def input_values(): parameter_list = { @@ -38,6 +41,7 @@ def time_constant(resistance, capaciatance): tc = resistance * capaciatance return tc + def max_current(max_voltage, resistance): mc = max_voltage / resistance return mc @@ -47,8 +51,16 @@ def max_current(max_voltage, resistance): # i+time_elapsed +def num_of_loops(solenoid_length, gauge_thickness): + n = solenoid_length / gauge_thickness + return n + + +# magnetic field (mf) calculations and area calculations + + def calc_mf_circular_solenoid(num_loops, current, diameter): - magnetic_field = scipy.mu_0 * num_loops * current / diameter + magnetic_field = scipy.constants.mu_0 * num_loops * current / diameter return magnetic_field @@ -58,7 +70,7 @@ def cross_section_area_circle(dia): # area calculation (cross section of soleno def calc_mf_square_solenoid(num_loops, current, side_length): - magnetic_field = np.sqrt(2) * scipy.mu_0 * num_loops * current / (scipy.pi * side_length / 2) + magnetic_field = np.sqrt(2) * scipy.constants.mu_0 * num_loops * current / (scipy.pi * side_length / 2) return magnetic_field @@ -68,7 +80,7 @@ def cross_section_area_square(side_length): # area calculation (cross section o def calc_mf_rect_solenoid(num_loops, current, length_short, length_long): - magnetic_field = (2 * scipy.mu_0 * num_loops * current / scipy.pi) * ( + magnetic_field = (2 * scipy.constants.mu_0 * num_loops * current / scipy.pi) * ( length_long / (length_short * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2))) + length_short / (length_long * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2)))) return magnetic_field @@ -85,7 +97,7 @@ def calc_mf_oval_solenoid(num_loops, current, length_short, length_long): # *** def calc_force(area, mf): - force = area * scipy.pow(mf, 2) / 2 / scipy.mu_0 + force = area * scipy.pow(mf, 2) / 2 / scipy.constants.mu_0 return force From cfb063829a0eb37b185e66b497bcdebefe46cc79 Mon Sep 17 00:00:00 2001 From: CashewTong Date: Sat, 11 Jan 2020 12:22:06 -0800 Subject: [PATCH 15/20] old version --- models/solenoids/GUIscratch.py | 100 +++++++ .../__pycache__/em_force_model.cpython-37.pyc | Bin 0 -> 2502 bytes models/solenoids/em_force_model.py | 282 ++++++------------ 3 files changed, 191 insertions(+), 191 deletions(-) create mode 100644 models/solenoids/GUIscratch.py create mode 100644 models/solenoids/__pycache__/em_force_model.cpython-37.pyc diff --git a/models/solenoids/GUIscratch.py b/models/solenoids/GUIscratch.py new file mode 100644 index 00000000..fe5f6ca2 --- /dev/null +++ b/models/solenoids/GUIscratch.py @@ -0,0 +1,100 @@ +from tkinter import * +from em_force_model import * + + + + +class solenoidGUI: + + def __init__(self, master): + self.master = master + master.title("window title") + # geometry: width x height + master.geometry('1080x720') + self.descriptionlabel = Label(master, text="Solenoid Model", font=("Arial Bold", 40)).grid( + column=0, row=0) + + # Changable Parameters + self.descriptionlabel = Label(master, text="Changable parameters: geometry", font=("Arial Bold", 20)).grid(column=0, row=1) + frame = Frame(master) + frame.grid(column=0, row=2) + + self.description_length_solenoid = Label(frame, text="Solenoid Length in mm").grid(column=0, row=1) + self.length_solenoid = Entry(frame, width = 10) + self.length_solenoid.grid (column = 1, row =1) + + self.description_gauge_thickness = Label(frame, text="Guage Thickness in mm").grid(column=0, row=2) + self.gauge_thickness = Entry(frame, width=10) + self.gauge_thickness.grid(column=1, row=2) + + # if circle, square, show + self.description_diameter = Label(frame, text="Diameter (square, circular)").grid(column=0, row=3) + self.diameter = Entry(frame, width=10) + self.diameter.grid(column=1, row=3) + + # if rectangle, oval, show + self.description_side_long = Label(frame, text="Length of longer side").grid(column=0, row=4) + self.side_long = Entry(frame, width=10) + self.side_long.grid(column=1, row=4) + + self.description_side_short = Label(frame, text="Length of shorter side").grid(column=0, row=5) + self.side_short = Entry(frame, width=10) + self.side_short.grid(column=1, row=5) + + # External Values, changeable, but dependent on other components + self.descriptionlabel2 = Label(master, text="Parameters: external circut", font=("Arial Bold", 20)).grid( + column=0, row=3) + frame2 = Frame(master) + frame2.grid(column=0, row=4) + + self.description_voltage= Label(frame2, text="Voltage in V").grid(column=0, row=1) + self.voltage = Entry(frame2, width=10) + self.voltage.grid(column=1, row=1) + + self.description_resistance = Label(frame2, text="resistance in ohms").grid(column=0, row=2) + self.resistance = Entry(frame2, width=10) + self.resistance.grid(column=1, row=2) + + + + + + # self.inputshape = Combobox(frame) + # self.inputshape['Shape of Solenoid'] = ("rectangle", "circle", "ellipse") + # combo.current("circle") # set the selected item + # combo.grid(column=0, row=0) + + + + + + + + + # click to solve + self.button = Button(master, text='Solve', command=self.calc) + self.button.grid (column = 0, row =9) + self.close_button = Button(master, text="Close", command=master.quit).grid(column = 0, row = 10) + # output + self.outputlabel = Label(master, text="output here") + self.outputlabel.grid(column=0, row=11) + + def calc(self): + n = num_of_loops(float(self.length_solenoid.get()), float(self.gauge_thickness.get())) + + i = max_current(float(self.voltage.get()), float(self.resistance.get())) + + # if circle + area = cross_section_area_circle(float(self.diameter.get())) + mf = calc_mf_circular_solenoid(n, i, float(self.diameter.get())) + + # if square + + # printed = calc_force(area, mf) + printed = (float(self.diameter.get())) + + self.outputlabel.configure(text = printed) + +root = Tk() +my_gui = solenoidGUI(root) +root.mainloop() \ No newline at end of file diff --git a/models/solenoids/__pycache__/em_force_model.cpython-37.pyc b/models/solenoids/__pycache__/em_force_model.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d144d534d3622dc5159068af456d42fbb3fe804e GIT binary patch literal 2502 zcmbVN%WmXE6m^x|9e1bm?z{tpff=R&0Si`W1OpS;AZ3scLb6&|#^rPz{OGBw&JfA7 z<0AmEm@N4eexbIk@(Zjux9sjbHAqye>fUOXea}7jQC}=9bRCTIdpkd@tvk-&w3!YL zE09ZKRjffSi@sQgToD^$6LM8-iEYR=u_JaN`+|S#4E8R7 z&KWS{9i*{7gwl!2Lg}c`DyBy?80I|Y6HN6w7QqC^&&BjGTLe+~e{^3sm4lCV4ljt8 z3wrN@c)0Lraj}drG5U{3zyC(#ug?Zuvy>&pNFRr)gi@v==sr(n5{{zDC^5cBqdd`x zG#!b4INgHJVMlEcC7iS7=UIu> z=W+#4Vxo`+5lFg?Lk~*jRIKm3;1z|E9a_KxS1#gF(5tuenw{%w=zPpucDId6| zrQ&paCh2YC<&*HEfoD2o%Gxn=jnk4!!Yt;|s7Q1ghev6WiJK6&kwbBqABAx$<4G3D zSxr2`+YM)ZCSSuYrt+deSP8RDiybK1dC4ji=`Q9u2YQYqVHE>nekj{Gfg~ZvOlw>| zM`iJGI^cneN;6(0ljt@qSt=DOqr1b9a66lmMbfhWmhxr@cj*A2op6S+r! z&&s$?`OPW4>e&QN%*g!;XB#gbGI<}nYvj(7p{Y6GZs?rW9G7pCxqVu0*xZh9b61=H z8mAkpC^;&?*cKp^7Urzuo?s(borG6db57h{r*bQ1=agjTN))o4D(>7kW=6YP>N z3YWEUm5Xa4DjWDet zua4w9c;~Ww&;sZq=+#H2Wv{54EOl*w?4t-L8(4cxeu&**-L&=DI7M)&JT7y^tl*v; zXQj^4A93B0X4;K($C)-Q^hWecn@DuM*~>=KEg-24+umk7i7iB17d8hZ#luo!0bD_A nqigRp{}Ha)NtS#{5mIEL$9>kr&v*R|zvXv)A8Y-av-1AGVU`2# literal 0 HcmV?d00001 diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index 9c542c94..56fc5e1e 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -1,103 +1,124 @@ - -# Purpose: Calculating the magnetic field strength at a point P, a certain distance away from the centre, -# along the axis to the direction the force is being exerted. -# -# Ampere’s law allows us to find the strength of a magnetic field (MF) within a solenoid, where the field is uniform. -# However, this does not apply outside the solenoid (at its edges). -# To find the MF strength at a point P outside the body of the solenoid, we use the following program. -# -# P is perpendicular to the cross section of the solenoid. +# Purpose: Calculating the magnetic field strength at the center of the solenoid using Biot Savart Law # This value is then used as an input to determine the electromagnetic force. +# For more information refer to 'Solenoid Research' (google docs) -# For more information and referenced diagram (page598), https: // www.mdpi.com / 2076 - 3417 / 5 / 3 / 595 / pdf.All # variables declarations used in this program are categorized into ... -# . values to be determined by design, values to be changed during play, output/calculated values +# values to be determined by design, values to be changed during play, output/calculated values + from typing import Dict + import scipy from scipy import constants +import matplotlib.pyplot as plt +import numpy as np -# Values determined by design, these being the parameters we can change by -# changing the design of the solenoid - def input_values(): parameter_list = { + 'length_solenoid': 10, # length of solenoid + 'wire_gauge': 1, # wire gauge + 'diameter': 1, # diameter of circular, side length of square + 'side_long': 2, # longer side for rect, longer value for ellipse + 'side_short': 1, # shorter side for rect, shorter value for ellipse + # External Values, changeable, but dependent on other components + 'max_voltage': 4, # the voltage across the capacitor + 'resistance': 1, # resistance of the device + 'capacitance': 3, # capacitance of our capacitor + + # input values, changes to model (visually) + + 'total_time': 5., # the time frame we wish to look at + 'time_interval': 0.2, # ### we want to change length of pulse } return parameter_list -def em_force_model(parameter_list): +def time_constant(resistance, capaciatance): + tc = resistance * capaciatance + return tc + - """ - :param parameter_list: From parameter list, for detailed information look into parameters list and below*** - :return: - """ +def max_current(max_voltage, resistance): + mc = max_voltage / resistance + return mc - length_solenoid = 10 # length of solenoid - outer_diameter = 14 # outer diameter of solenoid. This includes the width of the wires - inner_diameter = 8 # inner diameter of solenoid - # shell casing thickness (the frame we wrap wires around) - shell_casing_thickness = 7 - dist_p_to_center = 18 # distance from point P to center - num_coils = 100 # number of coils - cross_section_area_solenoid = scipy.power( - (inner_diameter / 2 + shell_casing_thickness), 2) * scipy.pi - # area calculation (cross section of solenoid) + # for i in range(0, parameter_list['total_time']): + # current_at_t.append(current(max_current, time_elapsed, time_constant)) + # i+time_elapsed - # External Values, changeable, but dependent on other components - max_voltage = 4 # the voltage across the capacitor - resistance = 1 # resistance of the device - capacitance = 3 # capacitance of our capacitor +def num_of_loops(solenoid_length, gauge_thickness): + n = solenoid_length / gauge_thickness + return n - # input values, these being values we can change during play, when we have - # finalized design - time_elapsed = 4 # ### we want to change length of pulse - direction_vector = 1 +# magnetic field (mf) calculations and area calculations - # Preliminary Calculations - time_constant = resistance * capacitance +def calc_mf_circular_solenoid(num_loops, current, diameter): + magnetic_field = scipy.constants.mu_0 * num_loops * current / diameter + return magnetic_field - max_current = max_voltage / resistance - current = max_current * scipy.power(scipy.e, -time_elapsed / time_constant) +def cross_section_area_circle(dia): # area calculation (cross section of solenoid) + area = scipy.power((dia / 2), 2) * scipy.pi + return area - print(current) - # The following are used for debugging purposes. They are arbitrary values - # and have no meaning in isolation +def calc_mf_square_solenoid(num_loops, current, side_length): + magnetic_field = np.sqrt(2) * scipy.constants.mu_0 * num_loops * current / (scipy.pi * side_length / 2) + return magnetic_field - # calling calculate_remanence function - remanence = calculate_remanence(current, length_solenoid, num_coils) - # calling calculate_constant_multiplier function - constant_multiplier = calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, - inner_diameter) +def cross_section_area_square(side_length): # area calculation (cross section of solenoid) + area = side_length * side_length + return area - length_add_distance_from_center = length_solenoid + 2 * dist_p_to_center - length_subtract_distance_from_center = length_solenoid - 2 * dist_p_to_center +def calc_mf_rect_solenoid(num_loops, current, length_short, length_long): + magnetic_field = (2 * scipy.constants.mu_0 * num_loops * current / scipy.pi) * ( + length_long / (length_short * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2))) + length_short / + (length_long * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2)))) + return magnetic_field - # calling calculate_ln_term_a function - ln_term_a = calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter) - # calling calculate_ln_term_b function - ln_term_b = calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter) +def cross_section_area_rect(length_long, length_short): # area calculation (cross section of solenoid) + area = length_short * length_long + return area - # calling calculating_field_strength function - field_strength_at_p = calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, - ln_term_a, length_subtract_distance_from_center, ln_term_b) - print(field_strength_at_p) - # calculating force - force_on_piston = calculate_force_on_piston(field_strength_at_p, - remanence, cross_section_area_solenoid, direction_vector) +def calc_mf_oval_solenoid(num_loops, current, length_short, length_long): # ****needs work + magnetic_field = 1 + return magnetic_field - print(force_on_piston) + +def calc_force(area, mf): + force = area * scipy.pow(mf, 2) / 2 / scipy.constants.mu_0 + return force + + +'''# time_elapsed = np.arange(0., parameter_list['total_time'], parameter_list['time_interval']) + + # plt.plot(time_elapsed, current(max_current, time_elapsed, time_constant), 'b--') + + plt.plot(time_elapsed, calculate_field_strength_at_p(calculate_constant_multiplier(parameter_list['num_coils'], + current(max_current, + time_elapsed, + time_constant), + parameter_list[ + 'length_solenoid'], + parameter_list['outer_diameter'], + parameter_list[ + 'inner_diameter']), + length_add_distance_from_center, + ln_term_a, + length_subtract_distance_from_center, + ln_term_b), + 'b--') + + plt.show()''' ## @@ -106,132 +127,11 @@ def em_force_model(parameter_list): ## +'''def current(max_current, time_elapsed, time_constant): + cur = max_current * scipy.power(scipy.e, -time_elapsed / time_constant) + return cur + +''' -def calculate_remanence(current, length_solenoid, num_coils): - """ - - Note: reference of physical aspects of parameters can be visualized and view on a diagram in research paper. - Since we split a lot of the many terms, the descriptions will need to be referred back to research paper of - equations for more clarification. - - :param current: - Current that is flowing through the wire - :param length_solenoid: - Length of the physical solenoid - :param num_coils: - Number of turns of coil - :return: - """ - - # this is used in the calculation for remanence - line_current_density: float = (current / length_solenoid) * num_coils - # remanent flux density (remanence) - return constants.mu_0 * line_current_density - - -def calculate_constant_multiplier(num_coils, current, length_solenoid, outer_diameter, inner_diameter): - """ - :param num_coils: - Number of turns of coil - :param current: - Current that is flowing through the wire - :param length_solenoid: - Length of the physical solenoid - :param outer_diameter: - Outer diameter of the physical solenoid - :param inner_diameter: - Inner diameter of the physical solenoid - :return: - """ - - constant_multiplier = (constants.mu_0 * num_coils * current) / \ - (2 * length_solenoid * (outer_diameter - inner_diameter)) - return constant_multiplier - - -def calculate_ln_term_a(outer_diameter, length_add_distance_from_center, inner_diameter): - """ - :param outer_diameter: - Outer diameter of the physical solenoid - :param length_add_distance_from_center: - Length_add_distance_from center term in equation in research paper - :param inner_diameter: - Inner diameter of the physical solenoid - :return: - """ - - ln_term_a = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_add_distance_from_center, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_add_distance_from_center, 2)))) - return ln_term_a - - -def calculate_ln_term_b(outer_diameter, length_subtract_distance_from_center, inner_diameter): - """ - :param outer_diameter: - Outer diameter of the physical solenoid - :param length_subtract_distance_from_center: - Length_subtract_distance_from center term in equation in research paper - :param inner_diameter: - Inner diameter of the physical solenoid - :return: - """ - - ln_term_b = scipy.log((outer_diameter + - scipy.sqrt(scipy.power(outer_diameter, 2) + - scipy.power(length_subtract_distance_from_center, 2))) / - (inner_diameter + - scipy.sqrt(scipy.power(inner_diameter, 2) + - scipy.power(length_subtract_distance_from_center, 2)))) - return ln_term_b - - -def calculate_field_strength_at_p(constant_multiplier, length_add_distance_from_center, ln_term_a, - length_subtract_distance_from_center, ln_term_b): - - """ - :param constant_multiplier: - Constant term in the beginning of equation in research paper - :param length_add_distance_from_center: - Length_add_distance_from center term in equation in research paper - :param ln_term_a: - Ln term a in equation reference in research paper - :param length_subtract_distance_from_center: - Length_subtract_distance_from center term in equation in research paper - :param ln_term_b: - Ln term b in equation reference in research paper - :return: - """ - - field_strength_at_p = constant_multiplier / length_add_distance_from_center * scipy.log(ln_term_a) \ - + constant_multiplier / length_subtract_distance_from_center * scipy.log(ln_term_b) - return field_strength_at_p - - -def calculate_force_on_piston(field_strength_at_p, remanence, cross_section_area_solenoid, direction_vector): - - """ - - :param field_strength_at_p: - Strength of magnetic field at point P on the medal kicking bar - :param remanence: - Value of ramanence - :param cross_section_area_solenoid: - The cross sectional area of the solenoid - :param direction_vector: - The directional vector in the direction the force is goign - :return: - """ - - force_on_piston = field_strength_at_p * remanence * \ - cross_section_area_solenoid * direction_vector / constants.mu_0 - return force_on_piston - -# DEFINING THE input_values FUNCTION AS THE MAIN FUNCTION - - -if __name__ == "__main__": - input_values() +# if __name__ == "__main__": +# input_values() \ No newline at end of file From bf7b52bff255059a31525b0a2d8b71e8bbe4f586 Mon Sep 17 00:00:00 2001 From: Anna Date: Sat, 11 Jan 2020 13:01:14 -0800 Subject: [PATCH 16/20] Fixed constants, updated model with Tkinter --- models/solenoids/.gitignore | 198 +++++++++++++++++++++++++++ models/solenoids/.idea/workspace.xml | 132 ------------------ models/solenoids/GUIscratch.py | 89 +++++++++++- models/solenoids/em_force_model.py | 2 +- 4 files changed, 287 insertions(+), 134 deletions(-) create mode 100644 models/solenoids/.gitignore delete mode 100644 models/solenoids/.idea/workspace.xml diff --git a/models/solenoids/.gitignore b/models/solenoids/.gitignore new file mode 100644 index 00000000..82b191b2 --- /dev/null +++ b/models/solenoids/.gitignore @@ -0,0 +1,198 @@ + +# Created by https://www.gitignore.io/api/python,pycharm +# Edit at https://www.gitignore.io/?templates=python,pycharm + +### PyCharm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### PyCharm Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +# *.iml +# modules.xml +# .idea/misc.xml +# *.ipr + +# Sonarlint plugin +.idea/**/sonarlint/ + +# SonarQube Plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator/ + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# End of https://www.gitignore.io/api/python,pycharm \ No newline at end of file diff --git a/models/solenoids/.idea/workspace.xml b/models/solenoids/.idea/workspace.xml deleted file mode 100644 index c7d6e89d..00000000 --- a/models/solenoids/.idea/workspace.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1573194861344 - - - - - - - \ No newline at end of file diff --git a/models/solenoids/GUIscratch.py b/models/solenoids/GUIscratch.py index ce013625..323c4d2b 100644 --- a/models/solenoids/GUIscratch.py +++ b/models/solenoids/GUIscratch.py @@ -1 +1,88 @@ -hello +from tkinter import * +from tkinter import ttk +from em_force_model import * + +class solenoidGUI: + + def __init__(self, master): + self.master = master + master.title("window title") + # geometry: width x height + master.geometry('1080x720') + self.description_label = Label(master, text="Solenoid Model", font=("Arial Bold", 40)).grid( + column=0, row=0) + + # Changeable Parameters + self.description_label = Label(master, text="Changeable parameters: geometry", font=("Arial Bold", 20)).grid(column=0, row=1) + frame = Frame(master) + frame.grid(column=0, row=2) + + self.description_length_solenoid = Label(frame, text="Solenoid Length in mm").grid(column=0, row=1) + self.length_solenoid = Entry(frame, width=10) + self.length_solenoid.grid (column=1, row=1) + + self.description_gauge_thickness = Label(frame, text="Gauge Thickness in mm").grid(column=0, row=2) + self.gauge_thickness = Entry(frame, width=10) + self.gauge_thickness.grid(column=1, row=2) + + # if circle, square, show + self.description_diameter = Label(frame, text="Diameter (square, circular)").grid(column=0, row=3) + self.diameter = Entry(frame, width=10) + self.diameter.grid(column=1, row=3) + + # if rectangle, oval, show + self.description_side_long = Label(frame, text="Length of longer side").grid(column=0, row=4) + self.side_long = Entry(frame, width=10) + self.side_long.grid(column=1, row=4) + + self.description_side_short = Label(frame, text="Length of shorter side").grid(column=0, row=5) + self.side_short = Entry(frame, width=10) + self.side_short.grid(column=1, row=5) + + # External Values, changeable, but dependent on other components + self.description_label2 = Label(master, text="Parameters: external circuit", font=("Arial Bold", 20)).grid( + column=0, row=3) + frame2 = Frame(master) + frame2.grid(column=0, row=4) + + self.description_voltage = Label(frame2, text="Voltage in V").grid(column=0, row=1) + self.voltage = Entry(frame2, width=10) + self.voltage.grid(column=1, row=1) + + self.description_resistance = Label(frame2, text="resistance in ohms").grid(column=0, row=2) + self.resistance = Entry(frame2, width=10) + self.resistance.grid(column=1, row=2) + + self.input_shape = ttk.Combobox(frame, values=["rectangle", "circle", "ellipse", "square"]) + self.input_shape.current(0) # set the selected item + self.input_shape.grid(column=0, row=0) + + # click to solve + self.button = Button(master, text='Solve', command=self.calc) + self.button.grid (column = 0, row =9) + self.close_button = Button(master, text="Close", command=master.quit).grid(column = 0, row = 10) + # output + self.output_label = Label(master, text="output here") + self.output_label.grid(column=0, row=11) + + def calc(self): + n = num_of_loops(float(self.length_solenoid.get()), float(self.gauge_thickness.get())) + + i = max_current(float(self.voltage.get()), float(self.resistance.get())) + + # get shape + + # if circle + area = cross_section_area_circle(float(self.diameter.get())) + mf = calc_mf_circular_solenoid(n, i, float(self.diameter.get())) + + # if square + + # printed = calc_force(area, mf) + printed = (float(self.diameter.get())) + + self.output_label.configure(text=printed) + +root = Tk() +my_gui = solenoidGUI(root) +root.mainloop() \ No newline at end of file diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index 9f528155..a6331f89 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -12,7 +12,7 @@ import matplotlib.pyplot as plt import numpy as np -__all__ = [constants] +# __all__ = [constants] def input_values(): From 01425e266fdf583c8308be76767ff50ab82cb9f7 Mon Sep 17 00:00:00 2001 From: Anna Date: Sat, 11 Jan 2020 20:02:38 -0800 Subject: [PATCH 17/20] changed wire gauge to drop down menu. circle, rect, square complete --- models/solenoids/GUIscratch.py | 54 +++++++++++++++++++++--------- models/solenoids/em_force_model.py | 15 ++++++--- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/models/solenoids/GUIscratch.py b/models/solenoids/GUIscratch.py index 323c4d2b..0ee84b93 100644 --- a/models/solenoids/GUIscratch.py +++ b/models/solenoids/GUIscratch.py @@ -2,8 +2,9 @@ from tkinter import ttk from em_force_model import * + class solenoidGUI: - + def __init__(self, master): self.master = master master.title("window title") @@ -13,16 +14,19 @@ def __init__(self, master): column=0, row=0) # Changeable Parameters - self.description_label = Label(master, text="Changeable parameters: geometry", font=("Arial Bold", 20)).grid(column=0, row=1) + self.description_label = Label(master, text="Changeable parameters: geometry", font=("Arial Bold", 20)).grid( + column=0, row=1) frame = Frame(master) frame.grid(column=0, row=2) self.description_length_solenoid = Label(frame, text="Solenoid Length in mm").grid(column=0, row=1) self.length_solenoid = Entry(frame, width=10) - self.length_solenoid.grid (column=1, row=1) + self.length_solenoid.grid(column=1, row=1) self.description_gauge_thickness = Label(frame, text="Gauge Thickness in mm").grid(column=0, row=2) - self.gauge_thickness = Entry(frame, width=10) + + self.gauge_thickness = ttk.Combobox(frame, values=["12", "13", "14", "15"]) + self.gauge_thickness.current(0) # set the selected item self.gauge_thickness.grid(column=1, row=2) # if circle, square, show @@ -59,30 +63,48 @@ def __init__(self, master): # click to solve self.button = Button(master, text='Solve', command=self.calc) - self.button.grid (column = 0, row =9) - self.close_button = Button(master, text="Close", command=master.quit).grid(column = 0, row = 10) + self.button.grid(column=0, row=9) + self.close_button = Button(master, text="Close", command=master.quit).grid(column=0, row=10) # output self.output_label = Label(master, text="output here") self.output_label.grid(column=0, row=11) def calc(self): - n = num_of_loops(float(self.length_solenoid.get()), float(self.gauge_thickness.get())) + # relating the combobox index to text + rectangle = 0 + circle = 1 + ellipse = 2 + square = 3 + + n = num_of_loops(float(self.length_solenoid.get()), float(self.gauge_thickness.get())) i = max_current(float(self.voltage.get()), float(self.resistance.get())) - # get shape + if self.input_shape.current() == rectangle: + area = cross_section_area_rect(float(self.side_short.get()), float(self.side_long.get())) + mf = calc_mf_rect_solenoid(n, i, float(self.side_short.get()), float(self.side_long.get())) + printed = calc_force(area, mf) + self.output_label.configure(text=printed) - # if circle - area = cross_section_area_circle(float(self.diameter.get())) - mf = calc_mf_circular_solenoid(n, i, float(self.diameter.get())) + if self.input_shape.current() == circle: + area = cross_section_area_circle(float(self.diameter.get())) + mf = calc_mf_circular_solenoid(n, i, float(self.diameter.get())) + printed = calc_force(area, mf) + self.output_label.configure(text=printed) - # if square + '''if self.input_shape.current() == ellipse: + area = cross_section_area_ellipse() + mf = calc_mf_ellipse_solenoid() + printed = calc_force(area, mf) + self.output_label.configure(text=printed)''' - # printed = calc_force(area, mf) - printed = (float(self.diameter.get())) + if self.input_shape.current() == square: + area = cross_section_area_square(float(self.diameter.get())) + mf = calc_mf_square_solenoid(n, i, float(self.diameter.get())) + printed = calc_force(area, mf) + self.output_label.configure(text=printed) - self.output_label.configure(text=printed) root = Tk() my_gui = solenoidGUI(root) -root.mainloop() \ No newline at end of file +root.mainloop() diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index a6331f89..6f6d5bf9 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -12,6 +12,7 @@ import matplotlib.pyplot as plt import numpy as np + # __all__ = [constants] @@ -81,8 +82,9 @@ def cross_section_area_square(side_length): # area calculation (cross section o def calc_mf_rect_solenoid(num_loops, current, length_short, length_long): magnetic_field = (2 * scipy.constants.mu_0 * num_loops * current / scipy.pi) * ( - length_long / (length_short * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2))) + length_short / - (length_long * np.sqrt(np.pow(length_long, 2) + np.pow(length_short, 2)))) + length_long / ( + length_short * np.sqrt(scipy.power(length_long, 2) + scipy.power(length_short, 2))) + length_short / + (length_long * np.sqrt(scipy.power(length_long, 2) + scipy.power(length_short, 2)))) return magnetic_field @@ -91,13 +93,18 @@ def cross_section_area_rect(length_long, length_short): # area calculation (cro return area -def calc_mf_oval_solenoid(num_loops, current, length_short, length_long): # ****needs work +def calc_mf_ellipse_solenoid(num_loops, current, length_short, length_long): # ****needs work magnetic_field = 1 return magnetic_field +def cross_section_area_ellipse(length_long, length_short): # area calculation (cross section of solenoid) + # area = 1 * 1 + return area + + def calc_force(area, mf): - force = area * scipy.pow(mf, 2) / 2 / scipy.constants.mu_0 + force = area * scipy.power(mf, 2) / 2 / scipy.constants.mu_0 return force From 749870a3311e0fdd951b7e09e88ff17be0f1b385 Mon Sep 17 00:00:00 2001 From: CashewTong Date: Tue, 14 Jan 2020 19:34:52 -0800 Subject: [PATCH 18/20] Fixed json loading problem, added json for AWG to mm conversion --- .gitignore | 112 ++++++++++++++++++ .idea/misc.xml | 3 + models/solenoids/GUIscratch.py | 30 +++-- .../__pycache__/em_force_model.cpython-37.pyc | Bin 2502 -> 0 bytes models/solenoids/awg_data.json | 55 +++++++++ models/solenoids/em_force_model.py | 1 + 6 files changed, 190 insertions(+), 11 deletions(-) delete mode 100644 models/solenoids/__pycache__/em_force_model.cpython-37.pyc create mode 100644 models/solenoids/awg_data.json diff --git a/.gitignore b/.gitignore index f01b8bf7..89bc960d 100644 --- a/.gitignore +++ b/.gitignore @@ -161,6 +161,115 @@ fabric.properties .idea/**/markdown-navigator.xml .idea/**/markdown-navigator/ + +# Created by https://www.gitignore.io/api/python +# Edit at https://www.gitignore.io/?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + ### venv ### # Virtualenv # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ @@ -182,3 +291,6 @@ venv.bak/ pip-selfcheck.json # End of https://www.gitignore.io/api/venv,pycharm + +# Mergetool files +*.orig diff --git a/.idea/misc.xml b/.idea/misc.xml index a8c5713c..eb9a4e16 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -4,4 +4,7 @@ + + \ No newline at end of file diff --git a/models/solenoids/GUIscratch.py b/models/solenoids/GUIscratch.py index 323c4d2b..8612704d 100644 --- a/models/solenoids/GUIscratch.py +++ b/models/solenoids/GUIscratch.py @@ -1,9 +1,8 @@ from tkinter import * from tkinter import ttk -from em_force_model import * - +from models.solenoids.em_force_model import * class solenoidGUI: - + def __init__(self, master): self.master = master master.title("window title") @@ -13,13 +12,14 @@ def __init__(self, master): column=0, row=0) # Changeable Parameters - self.description_label = Label(master, text="Changeable parameters: geometry", font=("Arial Bold", 20)).grid(column=0, row=1) + self.description_label = Label(master, text="Changeable parameters: geometry", font=("Arial Bold", 20)).grid(column=0, + row=1) frame = Frame(master) frame.grid(column=0, row=2) self.description_length_solenoid = Label(frame, text="Solenoid Length in mm").grid(column=0, row=1) self.length_solenoid = Entry(frame, width=10) - self.length_solenoid.grid (column=1, row=1) + self.length_solenoid.grid(column=1, row=1) self.description_gauge_thickness = Label(frame, text="Gauge Thickness in mm").grid(column=0, row=2) self.gauge_thickness = Entry(frame, width=10) @@ -59,8 +59,8 @@ def __init__(self, master): # click to solve self.button = Button(master, text='Solve', command=self.calc) - self.button.grid (column = 0, row =9) - self.close_button = Button(master, text="Close", command=master.quit).grid(column = 0, row = 10) + self.button.grid(column=0, row=9) + self.close_button = Button(master, text="Close", command=master.quit).grid(column=0, row=10) # output self.output_label = Label(master, text="output here") self.output_label.grid(column=0, row=11) @@ -71,7 +71,7 @@ def calc(self): i = max_current(float(self.voltage.get()), float(self.resistance.get())) # get shape - + # ​ # if circle area = cross_section_area_circle(float(self.diameter.get())) mf = calc_mf_circular_solenoid(n, i, float(self.diameter.get())) @@ -83,6 +83,14 @@ def calc(self): self.output_label.configure(text=printed) -root = Tk() -my_gui = solenoidGUI(root) -root.mainloop() \ No newline at end of file + +if __name__ == '__main__': + root = Tk() + my_gui = solenoidGUI(root) + root.mainloop() + # AWG conversions to mm + import json + + with open('awg_data.json', 'r') as awg_json: + awg_data = json.load(awg_json) + print(awg_data['AWG']) diff --git a/models/solenoids/__pycache__/em_force_model.cpython-37.pyc b/models/solenoids/__pycache__/em_force_model.cpython-37.pyc deleted file mode 100644 index d144d534d3622dc5159068af456d42fbb3fe804e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2502 zcmbVN%WmXE6m^x|9e1bm?z{tpff=R&0Si`W1OpS;AZ3scLb6&|#^rPz{OGBw&JfA7 z<0AmEm@N4eexbIk@(Zjux9sjbHAqye>fUOXea}7jQC}=9bRCTIdpkd@tvk-&w3!YL zE09ZKRjffSi@sQgToD^$6LM8-iEYR=u_JaN`+|S#4E8R7 z&KWS{9i*{7gwl!2Lg}c`DyBy?80I|Y6HN6w7QqC^&&BjGTLe+~e{^3sm4lCV4ljt8 z3wrN@c)0Lraj}drG5U{3zyC(#ug?Zuvy>&pNFRr)gi@v==sr(n5{{zDC^5cBqdd`x zG#!b4INgHJVMlEcC7iS7=UIu> z=W+#4Vxo`+5lFg?Lk~*jRIKm3;1z|E9a_KxS1#gF(5tuenw{%w=zPpucDId6| zrQ&paCh2YC<&*HEfoD2o%Gxn=jnk4!!Yt;|s7Q1ghev6WiJK6&kwbBqABAx$<4G3D zSxr2`+YM)ZCSSuYrt+deSP8RDiybK1dC4ji=`Q9u2YQYqVHE>nekj{Gfg~ZvOlw>| zM`iJGI^cneN;6(0ljt@qSt=DOqr1b9a66lmMbfhWmhxr@cj*A2op6S+r! z&&s$?`OPW4>e&QN%*g!;XB#gbGI<}nYvj(7p{Y6GZs?rW9G7pCxqVu0*xZh9b61=H z8mAkpC^;&?*cKp^7Urzuo?s(borG6db57h{r*bQ1=agjTN))o4D(>7kW=6YP>N z3YWEUm5Xa4DjWDet zua4w9c;~Ww&;sZq=+#H2Wv{54EOl*w?4t-L8(4cxeu&**-L&=DI7M)&JT7y^tl*v; zXQj^4A93B0X4;K($C)-Q^hWecn@DuM*~>=KEg-24+umk7i7iB17d8hZ#luo!0bD_A nqigRp{}Ha)NtS#{5mIEL$9>kr&v*R|zvXv)A8Y-av-1AGVU`2# diff --git a/models/solenoids/awg_data.json b/models/solenoids/awg_data.json new file mode 100644 index 00000000..7eb4a51d --- /dev/null +++ b/models/solenoids/awg_data.json @@ -0,0 +1,55 @@ +{ + "AWG": { + "12": { + "mm": "2.05232" + }, + "13": { + "mm": "1.8288" + }, + "14": { + "mm": "1.62814" + }, + "15": { + "mm": "1.45034" + }, + "16": { + "mm": "1.29032" + }, + "17": { + "mm": "1.15062" + }, + "18": { + "mm": "1.02362" + }, + "19": { + "mm": "0.91186" + }, + "20": { + "mm": "0.8128" + }, + "21": { + "mm": "0.7239" + }, + "22": { + "mm": "0.64516" + }, + "23": { + "mm": "0.57404" + }, + "24": { + "mm": "0.51054" + }, + "25": { + "mm": "0.45466" + }, + "26": { + "mm": "0.40386" + }, + "27": { + "mm": "0.36068" + }, + "28": { + "mm": "0.32004" + } + } +} \ No newline at end of file diff --git a/models/solenoids/em_force_model.py b/models/solenoids/em_force_model.py index b121940d..0b1321a3 100644 --- a/models/solenoids/em_force_model.py +++ b/models/solenoids/em_force_model.py @@ -9,6 +9,7 @@ from scipy import constants import matplotlib.pyplot as plt import numpy as np +from json import * def input_values(): From e4a7244adb70f8f54924b7f518a604a3fcf5cbf7 Mon Sep 17 00:00:00 2001 From: Anna Date: Sat, 15 Feb 2020 13:51:15 -0800 Subject: [PATCH 19/20] this is the magwire code from geophysik https://www.geophysik.uni-muenchen.de/~wack/teaching/Python/source/magwire/ --- models/MagWire/.idea/MagWire.iml | 13 ++ .../inspectionProfiles/profiles_settings.xml | 6 + models/MagWire/.idea/misc.xml | 4 + models/MagWire/.idea/modules.xml | 8 + models/MagWire/.idea/vcs.xml | 6 + models/MagWire/.idea/workspace.xml | 114 ++++++++++ models/MagWire/biotsavart.py | 110 ++++++++++ models/MagWire/magwire.py | 63 ++++++ models/MagWire/palint_oven.py | 80 +++++++ models/MagWire/sinusoidal_loop_demag.py | 113 ++++++++++ models/MagWire/solenoid_demo.py | 91 ++++++++ models/MagWire/wire.py | 205 ++++++++++++++++++ models/solenoids/GUIscratch.py | 3 +- 13 files changed, 815 insertions(+), 1 deletion(-) create mode 100644 models/MagWire/.idea/MagWire.iml create mode 100644 models/MagWire/.idea/inspectionProfiles/profiles_settings.xml create mode 100644 models/MagWire/.idea/misc.xml create mode 100644 models/MagWire/.idea/modules.xml create mode 100644 models/MagWire/.idea/vcs.xml create mode 100644 models/MagWire/.idea/workspace.xml create mode 100644 models/MagWire/biotsavart.py create mode 100644 models/MagWire/magwire.py create mode 100644 models/MagWire/palint_oven.py create mode 100644 models/MagWire/sinusoidal_loop_demag.py create mode 100644 models/MagWire/solenoid_demo.py create mode 100644 models/MagWire/wire.py diff --git a/models/MagWire/.idea/MagWire.iml b/models/MagWire/.idea/MagWire.iml new file mode 100644 index 00000000..85c7612b --- /dev/null +++ b/models/MagWire/.idea/MagWire.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/models/MagWire/.idea/inspectionProfiles/profiles_settings.xml b/models/MagWire/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 00000000..105ce2da --- /dev/null +++ b/models/MagWire/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/models/MagWire/.idea/misc.xml b/models/MagWire/.idea/misc.xml new file mode 100644 index 00000000..3d64936d --- /dev/null +++ b/models/MagWire/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/models/MagWire/.idea/modules.xml b/models/MagWire/.idea/modules.xml new file mode 100644 index 00000000..194e2f29 --- /dev/null +++ b/models/MagWire/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/models/MagWire/.idea/vcs.xml b/models/MagWire/.idea/vcs.xml new file mode 100644 index 00000000..b2bdec2d --- /dev/null +++ b/models/MagWire/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/models/MagWire/.idea/workspace.xml b/models/MagWire/.idea/workspace.xml new file mode 100644 index 00000000..a12dc72b --- /dev/null +++ b/models/MagWire/.idea/workspace.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1581798536045 + + + + + + + \ No newline at end of file diff --git a/models/MagWire/biotsavart.py b/models/MagWire/biotsavart.py new file mode 100644 index 00000000..561be496 --- /dev/null +++ b/models/MagWire/biotsavart.py @@ -0,0 +1,110 @@ +__author__ = 'wack' + +# part of the magwire package + +# calculate magnetic fields arising from electrical current through wires of arbitrary shape +# with the law of Biot-Savart + +# written by Michael Wack +# wack@geophysik.uni-muenchen.de + +# tested with python 3.4.3 + + +import numpy as np +import time +#import multiprocessing as mp +from matplotlib import pyplot as plt +import mpl_toolkits.mplot3d.axes3d as ax3d + +class BiotSavart: + ''' + calculates the magnetic field generated by currents flowing through wires + ''' + + def __init__(self, wire=None): + self.wires = [] + if wire is not None: + self.wires.append(wire) + + def AddWire(self, wire): + self.wires.append(wire) + + def CalculateB(self, points): + """ + calculate magnetic field B at given points + :param points: numpy array of n points (xyz) + :return: numpy array of n vectors representing the B field at given points + """ + + print("found {} wire(s).".format(len(self.wires))) + c = 0 + # generate list of IdL and r1 vectors from all wires + for w in self.wires: + c += 1 + _IdL, _r1 = w.IdL_r1 + print("wire {} has {} segments".format(c, len(_IdL))) + if c == 1: + IdL = _IdL + r1 = _r1 + else: + IdL = np.vstack((IdL, _IdL)) + r1 = np.vstack((r1, _r1)) + print("total number of segments: {}".format(len(IdL))) + print("number of field points: {}".format(len(points))) + print("total number of calculations: {}".format(len(points)*len(IdL))) + + # now we have + # all segment vectors multiplied by the flowing current in IdL + # and all vectors to the central points of the segments in r1 + + # calculate vector B*1e7 for each point in space + t1 = time.process_time() + # simple list comprehension to calculate B at each point r + B = np.array([BiotSavart._CalculateB1(r, IdL, r1) * 1e-7 for r in points]) + + # multi processing + # slower than single processing? + #pool = mp.Pool(processes=16) + #B = np.array([pool.apply(_CalculateB1, args=(r, IdL, r1)) for r in points]) + + t2 = time.process_time() + print("time needed for calculation: {} s".format(t2-t1)) + + return B + + def vv_PlotWires(self): + for w in self.wires: + w.vv_plot_path() + + def mpl3d_PlotWires(self, ax): + for w in self.wires: + w.mpl3d_plot_path(show=False, ax=ax) + + + + + @staticmethod + def _CalculateB1(r, IdL, r1): + ''' + calculate magnetic field B for one point r in space + :param r: 3 component numpy array representing the location where B will be calculated + :param IdL: all segment vectors multiplied by the flowing current + :param r1: all vectors to the central points of the segments + :return: numpy array of 3 component vector of B multiplied by 1e7 + ''' + + # calculate law of biot savart for all current elements at given point r + r2 = r - r1 + r25 = np.linalg.norm(r2, axis=1)**3 + r3 = r2 / r25[:, np.newaxis] + + cr = np.cross(IdL, r3) + + # claculate sum of contributions from all current elements + s = np.sum(cr, axis=0) + + return s + + + diff --git a/models/MagWire/magwire.py b/models/MagWire/magwire.py new file mode 100644 index 00000000..8d78b4d3 --- /dev/null +++ b/models/MagWire/magwire.py @@ -0,0 +1,63 @@ +__author__ = 'wack' + +# part of the magwire package + +# calculate magnetic fields arising from electrical current through wires of arbitrary shape +# with the law of Biot-Savart + +# written by Michael Wack 2015 +# wack@geophysik.uni-muenchen.de + +# tested with python 3.4.3 + +# some basic calculations for testing + + +import numpy as np + +import visvis as vv + +import wire +import biotsavart + + +# simple solenoid +w = wire.Wire(path=wire.Wire.SolenoidPath(), discretization_length=0.01, current=100).Translate((0.1, 0.1, 0)).Rotate(axis=(1, 0, 0), deg=45) +sol = biotsavart.BiotSavart(wire=w) + +resolution = 0.02 +volume_corner1 = (-.2, -.3, -.2) +volume_corner2 = (.3, .3, .4) + +grid = np.mgrid[volume_corner1[0]:volume_corner2[0]:resolution, volume_corner1[1]:volume_corner2[1]:resolution, volume_corner1[2]:volume_corner2[2]:resolution] + +# create list of grid points +points = np.vstack(map(np.ravel, grid)).T + +# calculate B field at given points +B = sol.CalculateB(points=points) + +Babs = np.linalg.norm(B, axis=1) + +# draw results + +# prepare axes +a = vv.gca() +a.cameraType = '3d' +a.daspectAuto = False + +vol = Babs.reshape(grid.shape[1:]).T +vol = np.clip(vol, 0.002, 0.01) +vol = vv.Aarray(vol, sampling=(resolution, resolution, resolution), origin=(volume_corner1[2], volume_corner1[1], volume_corner1[0])) + +# set labels +vv.xlabel('x axis') +vv.ylabel('y axis') +vv.zlabel('z axis') + +sol.vv_PlotWires() + +t = vv.volshow2(vol, renderStyle='mip', cm=vv.CM_JET) +vv.colorbar() +app = vv.use() +app.Run() diff --git a/models/MagWire/palint_oven.py b/models/MagWire/palint_oven.py new file mode 100644 index 00000000..065ee9dd --- /dev/null +++ b/models/MagWire/palint_oven.py @@ -0,0 +1,80 @@ +__author__ = 'wack' + +# part of the magwire package + +# calculate magnetic fields arising from electrical current through wires of arbitrary shape +# with the law of Biot-Savart + +# written by Michael Wack 2015 +# wack@geophysik.uni-muenchen.de + +# tested with python 3.4.3 + +# calculate fields needed for an palint oven + +import numpy as np +import matplotlib.pyplot as plt +from copy import deepcopy +import wire +import biotsavart + +# two solenoids + +w1 = wire.Wire(path=wire.Wire.SolenoidPath(radius=0.1, pitch=0.02, turns=20), discretization_length=0.01, current=10).Rotate(axis=(0, 1, 0), deg=90) +w2 = wire.Wire(path=wire.Wire.SolenoidPath(radius=0.1, pitch=0.02, turns=30), discretization_length=0.01, current=20).Rotate(axis=(0, 1, 0), deg=90).Translate([.45,0,0]) + +sol = biotsavart.BiotSavart(wire=w1) +sol.AddWire(w2) + +resolution = 0.01 +xy_corner1 = (-.2, -.09) +xy_corner2 = (.8+1e-10, .09) + +# matplotlib plot 2D +# create list of xy coordinates +grid = np.mgrid[xy_corner1[0]:xy_corner2[0]:resolution, xy_corner1[1]:xy_corner2[1]:resolution] + +# create list of grid points +points = np.vstack(map(np.ravel, grid)).T +points = np.hstack([points, np.zeros([len(points),1])]) + +# calculate B field at given points +B = sol.CalculateB(points=points) +Babs = np.linalg.norm(B, axis=1) + +# remove big values close to the wire +#cutoff = 0.005 + +#B[Babs > cutoff] = [np.nan,np.nan,np.nan] +#Babs[Babs > cutoff] = np.nan + + + +#2d quiver +# get 2D values from one plane with Z = 0 + +fig = plt.figure() +ax = fig.gca() +ax.quiver(points[:, 0], points[:, 1], B[:, 0], B[:, 1], scale=.15) +X = np.unique(points[:, 0]) +Y = np.unique(points[:, 1]) +cs = ax.contour(X, Y, Babs.reshape([len(X), len(Y)]).T, 10) +ax.clabel(cs) +plt.xlabel('x') +plt.ylabel('y') +plt.axis('equal') +plt.show() + + +x_vals = np.arange(xy_corner1[0],xy_corner2[0],resolution) +points = np.array( [x_vals, x_vals*0, x_vals*0]).T +print(points) +B = sol.CalculateB(points=points) +Babs = np.linalg.norm(B, axis=1) + +fig = plt.figure() +plt.plot(points[:,0], Babs) +plt.xlabel('x[m]') +plt.ylabel('B[T]') +plt.show() + diff --git a/models/MagWire/sinusoidal_loop_demag.py b/models/MagWire/sinusoidal_loop_demag.py new file mode 100644 index 00000000..fa985b5d --- /dev/null +++ b/models/MagWire/sinusoidal_loop_demag.py @@ -0,0 +1,113 @@ +__author__ = 'wack' + + +# part of the magwire package + +# calculate magnetic fields arising from electrical current through wires of arbitrary shape +# with the law of Biot-Savart + +# written by Michael Wack 2015 +# wack@geophysik.uni-muenchen.de + +# tested with python 3.4.3 + + +# calculate magnetic field caused by two sinusoidal loops with opposing current directions + +import numpy as np + +try: + import visvis as vv + visvis_avail = True +except ImportError: + visvis_avail = False + print("visvis not found.") + +from matplotlib import pyplot as plt +from mpl_toolkits.mplot3d import axes3d + +import wire +import biotsavart + + +npts = 200 +radius = .07 +amp = .01 +ncycle = 12.0 + + +# define wires +w1 = wire.Wire(path=wire.Wire.SinusoidalCircularPath(radius=radius, amplitude=amp, frequency=ncycle, pts=npts), discretization_length=0.01, current=100.0) +w2 = wire.Wire(path=wire.Wire.SinusoidalCircularPath(radius=radius, amplitude=amp, frequency=ncycle, pts=npts), discretization_length=0.01, current=-100.0).Rotate(axis=(0, 0, 1), deg=360.0/ncycle/2.0) + +# prepare data grid and calculate B in volume +resolution = 0.005 +# volume to examine +volume_corner1 = (0, 0, 0) +volume_corner2 = (.12, .12, .05) + +grid3D = np.mgrid[volume_corner1[0]:volume_corner2[0]:resolution, volume_corner1[1]:volume_corner2[1]:resolution, volume_corner1[2]:volume_corner2[2]:resolution] +grid2D = np.mgrid[volume_corner1[0]:volume_corner2[0]:resolution/2.0, volume_corner1[1]:volume_corner2[1]:resolution/2.0, 0:1] + +# create list of grid points +points3D = np.vstack(map(np.ravel, grid3D)).T +points2D = np.vstack(map(np.ravel, grid2D)).T + +# calculate B field at given points +bs = biotsavart.BiotSavart(wire=w1) +bs.AddWire(w2) + +B = bs.CalculateB(points=points3D) +Babs = np.linalg.norm(B, axis=1) + +B2D = bs.CalculateB(points=points2D) +B2Dabs = np.linalg.norm(B2D, axis=1) +B2Dabs = B2Dabs.clip(0,0.01) +B2Dabsgrid = B2Dabs.reshape(grid2D.shape[1:-1]).T + + +# draw results + +# prepare axes +a = vv.gca() +a.cameraType = '3d' +a.daspectAuto = False + +#Bgrid = B.reshape(grid3D.shape).T +Babsgrid = Babs.reshape(grid3D.shape[1:]).T + +# clipping is not automatic! +Babsgrid = np.clip(Babsgrid, 0, 0.005) +Babsgrid = vv.Aarray(Babsgrid, sampling=(resolution, resolution, resolution), + origin=(volume_corner1[2], volume_corner1[1], volume_corner1[0])) + + +# set labels +vv.xlabel('x axis') +vv.ylabel('y axis') +vv.zlabel('z axis') + +bs.vv_PlotWires() + +t = vv.volshow2(Babsgrid, renderStyle='mip', cm=vv.CM_JET) +vv.colorbar() +app = vv.use() +app.Run() + + +# matplotlib plot + +fig = plt.figure() + +# 3d quiver + +#ax = fig.gca(projection='3d') +#ax.quiver(points[:, 0], points[:, 1], points[:, 2], B[:, 0], B[:, 1], B[:, 2], length=0.005) + +#2d quiver +ax = fig.gca() +ax.quiver(points2D[:, 0], points2D[:, 1], B2D[:, 0], B2D[:, 1], scale=.3) +cs = ax.contour(grid2D.reshape(grid2D.shape[:-1])[0], grid2D.reshape(grid2D.shape[:-1])[1], B2Dabsgrid) +ax.clabel(cs) + +plt.show() diff --git a/models/MagWire/solenoid_demo.py b/models/MagWire/solenoid_demo.py new file mode 100644 index 00000000..174e819e --- /dev/null +++ b/models/MagWire/solenoid_demo.py @@ -0,0 +1,91 @@ +__author__ = 'wack' + +# part of the magwire package + +# calculate magnetic fields arising from electrical current through wires of arbitrary shape +# with the law of Biot-Savart + +# written by Michael Wack 2015 +# wack@geophysik.uni-muenchen.de + +# tested with python 3.4.3 + +# some basic calculations for testing + +import numpy as np +import matplotlib.pyplot as plt +import wire +import biotsavart + + +# simple solenoid +# approximated analytical solution: B = mu0 * I * n / l = 4*pi*1e-7[T*m/A] * 100[A] * 10 / 0.5[m] = 2.5mT + + +w = wire.Wire(path=wire.Wire.SolenoidPath(pitch=0.05, turns=10), discretization_length=0.01, current=100).Rotate(axis=(1, 0, 0), deg=90) #.Translate((0.1, 0.1, 0)). +sol = biotsavart.BiotSavart(wire=w) + +resolution = 0.04 +volume_corner1 = (-.2, -.8, -.2) +volume_corner2 = (.2+1e-10, .3, .2) + +# matplotlib plot 2D +# create list of xy coordinates +grid = np.mgrid[volume_corner1[0]:volume_corner2[0]:resolution, volume_corner1[1]:volume_corner2[1]:resolution] + +# create list of grid points +points = np.vstack(map(np.ravel, grid)).T +points = np.hstack([points, np.zeros([len(points),1])]) + +# calculate B field at given points +B = sol.CalculateB(points=points) + + +Babs = np.linalg.norm(B, axis=1) + +# remove big values close to the wire +cutoff = 0.005 + +B[Babs > cutoff] = [np.nan,np.nan,np.nan] +#Babs[Babs > cutoff] = np.nan + +for ba in B: + print(ba) + +#2d quiver +# get 2D values from one plane with Z = 0 + +fig = plt.figure() +ax = fig.gca() +ax.quiver(points[:, 0], points[:, 1], B[:, 0], B[:, 1], scale=.15) +X = np.unique(points[:, 0]) +Y = np.unique(points[:, 1]) +cs = ax.contour(X, Y, Babs.reshape([len(X), len(Y)]).T, 10) +ax.clabel(cs) +plt.xlabel('x') +plt.ylabel('y') +plt.axis('equal') +plt.show() + + +# matplotlib plot 3D + +grid = np.mgrid[volume_corner1[0]:volume_corner2[0]:resolution*2, volume_corner1[1]:volume_corner2[1]:resolution*2, volume_corner1[2]:volume_corner2[2]:resolution*2] + +# create list of grid points +points = np.vstack(map(np.ravel, grid)).T + +# calculate B field at given points +B = sol.CalculateB(points=points) + +Babs = np.linalg.norm(B, axis=1) + +fig = plt.figure() +# 3d quiver +ax = fig.gca(projection='3d') +sol.mpl3d_PlotWires(ax) +ax.quiver(points[:, 0], points[:, 1], points[:, 2], B[:, 0], B[:, 1], B[:, 2], length=0.04) +plt.show() + + + diff --git a/models/MagWire/wire.py b/models/MagWire/wire.py new file mode 100644 index 00000000..c0d6a569 --- /dev/null +++ b/models/MagWire/wire.py @@ -0,0 +1,205 @@ +__author__ = 'wack' + +# part of the magwire package + +# calculate magnetic fields arising from electrical current through wires of arbitrary shape +# with the law of Biot-Savart + +# written by Michael Wack +# wack@geophysik.uni-muenchen.de + +# tested with python 3.4.3 + +from copy import deepcopy +import numpy as np +try: + import visvis as vv + visvis_avail = True +except ImportError: + visvis_avail = False + print("visvis not found.") + + +class Wire: + ''' + represents an arbitrary 3D wire geometry + ''' + def __init__(self, current=1, path=None, discretization_length=0.01): + ''' + + :param current: electrical current in Ampere used for field calculations + :param path: geometry of the wire specified as path of n 3D (x,y,z) points in a numpy array with dimension n x 3 + length unit is meter + :param discretization_length: lenght of dL after discretization + ''' + self.current = current + self.path = path + self.discretization_length = discretization_length + + + @property + def discretized_path(self): + ''' + calculate end points of segments of discretized path + approximate discretization lenghth is given by self.discretization_length + elements will never be combined + elements longer that self.dicretization_length will be divided into pieces + :return: discretized path as m x 3 numpy array + ''' + + try: + return self.dpath + except AttributeError: + pass + + self.dpath = deepcopy(self.path) + for c in range(len(self.dpath)-2, -1, -1): + # go backwards through all elements + # length of element + element = self.dpath[c+1]-self.dpath[c] + el_len = np.linalg.norm(element) + npts = int(np.ceil(el_len / self.discretization_length)) # number of parts that this element should be split up into + if npts > 1: + # element too long -> create points between + # length of new sub elements + sel = el_len / float(npts) + for d in range(npts-1, 0, -1): + self.dpath = np.insert(self.dpath, c+1, self.dpath[c] + element / el_len * sel * d, axis=0) + + return self.dpath + + @property + def IdL_r1(self): + ''' + calculate discretized path elements dL and their center point r1 + :return: numpy array with I * dL vectors, numpy array of r1 vectors (center point of element dL) + ''' + npts = len(self.discretized_path) + if npts < 2: + print("discretized path must have at least two points") + return + + IdL = np.array([self.discretized_path[c+1]-self.discretized_path[c] for c in range(npts-1)]) * self.current + r1 = np.array([(self.discretized_path[c+1]+self.discretized_path[c])*0.5 for c in range(npts-1)]) + + return IdL, r1 + + + def vv_plot_path(self, discretized=True, color='r'): + if not visvis_avail: + print("plot path works only with visvis module") + return + + if discretized: + p = self.discretized_path + else: + p = self.path + + vv.plot(p, ms='x', mc=color, mw='2', ls='-', mew=0) + + + def mpl3d_plot_path(self, discretized=True, show=True, ax=None, plt_style='-r'): + + if ax is None: + fig = plt.figure(None) + ax = ax3d.Axes3D(fig) + + if discretized: + p = self.discretized_path + else: + p = self.path + + ax.plot(p[:, 0], p[:, 1], p[:, 2], plt_style) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + + # make all axes the same + #max_a = np.array((p[:, 0], p[:, 1], p[:, 2])).max() + + #ax.set_xlim3d(min(p[:, 0]), max_a) + #ax.set_ylim3d(min(p[:, 1]), max_a) + #ax.set_zlim3d(min(p[:, 2]), max_a) + + + if show: + plt.show() + + return ax + + def ExtendPath(self, path): + ''' + extends existing path by another one + :param path: path to append + ''' + if self.path is None: + self.path = path + else: + # check if last point is identical to avoid zero length segments + if self.path[-1] == path[0]: + self.path=np.append(self.path, path[1:], axis=1) + else: + self.path=np.append(self.path, path, axis=1) + + def Translate(self, xyz): + ''' + move the wire in space + :param xyz: 3 component vector that describes translation in x,y and z direction + ''' + if self.path is not None: + self.path += np.array(xyz) + + return self + + def Rotate(self, axis=(1,0,0), deg=0): + ''' + rotate wire around given axis by deg degrees + :param axis: axis of rotation + :param deg: angle + ''' + if self.path is not None: + n = axis + ca = np.cos(np.radians(deg)) + sa = np.sin(np.radians(deg)) + R = np.array([[n[0]**2*(1-ca)+ca, n[0]*n[1]*(1-ca)-n[2]*sa, n[0]*n[2]*(1-ca)+n[1]*sa], + [n[1]*n[0]*(1-ca)+n[2]*sa, n[1]**2*(1-ca)+ca, n[1]*n[2]*(1-ca)-n[0]*sa], + [n[2]*n[0]*(1-ca)-n[1]*sa, n[2]*n[1]*(1-ca)+n[0]*sa, n[2]**2*(1-ca)+ca]]) + self.path = np.dot(self.path, R.T) + + return self + + + + # different standard paths + @staticmethod + def LinearPath(pt1=(0, 0, 0), pt2=(0, 0, 1)): + return np.array([pt1, pt2]).T + + @staticmethod + def RectangularPath(dx=0.1, dy=0.2): + dx2 = dx/2.0; dy2 = dy/2.0 + return np.array([[dx2, dy2, 0], [dx2, -dy2, 0], [-dx2, -dy2, 0], [-dx2, dy2, 0], [dx2, dy2, 0]]).T + + @staticmethod + def CircularPath(radius=0.1, pts=20): + return Wire.EllipticalPath(rx=radius, ry=radius, pts=pts) + + @staticmethod + def SinusoidalCircularPath(radius=0.1, amplitude=0.01, frequency=10, pts=100): + t = np.linspace(0, 2 * np.pi, pts) + return np.array([radius * np.sin(t), radius * np.cos(t), amplitude * np.cos(frequency*t)]).T + + @staticmethod + def EllipticalPath(rx=0.1, ry=0.2, pts=20): + t = np.linspace(0, 2 * np.pi, pts) + return np.array([rx * np.sin(t), ry * np.cos(t), 0]).T + + @staticmethod + def SolenoidPath(radius=0.1, pitch=0.01, turns=30, pts_per_turn=20): + return Wire.EllipticalSolenoidPath(rx=radius, ry=radius, pitch=pitch, turns=turns, pts_per_turn=pts_per_turn) + + @staticmethod + def EllipticalSolenoidPath(rx=0.1, ry=0.2, pitch=0.01, turns=30, pts_per_turn=20): + t = np.linspace(0, 2 * np.pi * turns, pts_per_turn * turns) + return np.array([rx * np.sin(t), ry * np.cos(t), t / (2 * np.pi) * pitch]).T + diff --git a/models/solenoids/GUIscratch.py b/models/solenoids/GUIscratch.py index c32fec6e..e5c205f1 100644 --- a/models/solenoids/GUIscratch.py +++ b/models/solenoids/GUIscratch.py @@ -1,6 +1,7 @@ from tkinter import * from tkinter import ttk -from models.solenoids.em_force_model import * +from em_force_model import * + class solenoidGUI: def __init__(self, master): From 803b312d492a0f77c17a9cffb296dea623104768 Mon Sep 17 00:00:00 2001 From: Anna Date: Sat, 15 Feb 2020 13:56:49 -0800 Subject: [PATCH 20/20] . --- models/MagWire/palint_oven.py | 1 + 1 file changed, 1 insertion(+) diff --git a/models/MagWire/palint_oven.py b/models/MagWire/palint_oven.py index 065ee9dd..5d3db58c 100644 --- a/models/MagWire/palint_oven.py +++ b/models/MagWire/palint_oven.py @@ -23,6 +23,7 @@ w1 = wire.Wire(path=wire.Wire.SolenoidPath(radius=0.1, pitch=0.02, turns=20), discretization_length=0.01, current=10).Rotate(axis=(0, 1, 0), deg=90) w2 = wire.Wire(path=wire.Wire.SolenoidPath(radius=0.1, pitch=0.02, turns=30), discretization_length=0.01, current=20).Rotate(axis=(0, 1, 0), deg=90).Translate([.45,0,0]) + sol = biotsavart.BiotSavart(wire=w1) sol.AddWire(w2)