Source code for magpylib._lib.classes.currents

# -------------------------------------------------------------------------------
# magpylib -- A Python 3 toolbox for working with magnetic fields.
# Copyright (C) Silicon Austria Labs, https://silicon-austria-labs.com/,
#               Michael Ortner <magpylib@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program.  If not, see <https://www.gnu.org/licenses/>.
# The acceptance of the conditions of the GNU Affero General Public License are
# compulsory for the usage of the software.
#
# For contact information, reach out over at <magpylib@gmail.com> or our issues
# page at https://www.github.com/magpylib/magpylib/issues.
# -------------------------------------------------------------------------------

from numpy import array, float64, ndarray, shape, ones, tile
from magpylib._lib.mathLib import angleAxisRotation_priv
from magpylib._lib.fields.Current_Line_vector import Bfield_CurrentLineV, Bfield_CurrentLineVV
from magpylib._lib.fields.Current_CircularLoop import Bfield_CircularCurrentLoop
from magpylib._lib.fields.Current_CircularLoop_vector import Bfield_CircularCurrentLoopV
from magpylib._lib.classes.base import LineCurrent
from magpylib._lib.mathLib_vector import angleAxisRotationV_priv


# tool-tip / intellisense helpers ---------------------------------------------
# Class initialization is done purely by kwargs. While some # of these can be 
# set to zero by default other MUST be given to make any sense 
# (e.g. magnetization). To improve tool tips and intellisense we inizilize them
# with names, e.g. mag=(Mx, My, Mz). This looks good, but it requires that
# these names are pre-initialzed:
from typing import List, Tuple, TypeVar
x_i = TypeVar('x_i', int, float)
y_i = TypeVar('y_i', int, float)
z_i = TypeVar('z_i', int, float)
listOfPos = List[Tuple[x_i, y_i, z_i]]

I = .0 
d = .0



# -------------------------------------------------------------------------------
[docs]class Circular(LineCurrent): """ A circular line current loop with diameter `dim` and a current `curr` flowing in positive orientation. In the canonical basis (position=[0,0,0], angle=0.0, axis=[0,0,1]) the loop lies in the x-y plane with the origin at its center. Scalar input is either integer or float. Vector input format can be either list, tuple or array of any data type (float, int). Parameters ---------- curr : scalar [A] Set current in loop in units of [A] dim : float [mm] Set diameter of current loop in units of [mm] pos=[0,0,0] : vec3 [mm] Set position of the center of the current loop in units of [mm]. angle=0.0 : scalar [deg] Set angle of orientation of current loop in units of [deg]. axis=[0,0,1] : vec3 [] Set axis of orientation of the current loop. Attributes ---------- current : float [A] Current in loop in units of [A] dimension : float [mm] Loop diameter in units of [mm] position : arr3 [mm] Position of center of loop in units of [mm] angle : float [deg] Angle of orientation of the current loop. axis : arr3 [] Axis of orientation of the current loop. Example ------- >>> from magpylib import source >>> cd = source.current.Circular(curr=10,dim=2) >>> B = cd.getB([0,0,2]) >>> print(B) [0. 0. 0.56198518] Note ---- The following Methods are available to all sources objects. """ def __init__(self, curr=I, dim=d, pos=(0.0, 0.0, 0.0), angle=0.0, axis=(0.0, 0.0, 1.0)): # inherit class lineCurrent # - pos, Mrot, MrotInv, curr # - moveBy, rotateBy LineCurrent.__init__(self, pos, angle, axis, curr) # secure input type and check input format of dim assert dim >= 0, 'Bad input dimension' self.dimension = float(dim)
[docs] def getB(self, pos): # Particular Circular current B field calculation. Check RCS for getB() interface # vectorized code if input is an Nx3 array if type(pos) == ndarray: if len(shape(pos))==2: # list of positions - use vectorized code # vector size NN = shape(pos)[0] # prepare vector inputs POSREL = pos - self.position ANG = ones(NN)*self.angle AX = tile(self.axis,(NN,1)) DIM = ones(NN)*self.dimension CURR = ones(NN)*self.current # compute rotations and field ROTATEDPOS = angleAxisRotationV_priv(ANG, -AX, POSREL) BB = Bfield_CircularCurrentLoopV(CURR,DIM,ROTATEDPOS) BCM = angleAxisRotationV_priv(ANG, AX, BB) return BCM # secure input type and check input format p1 = array(pos, dtype=float64, copy=False) # relative position between mag and obs posRel = p1 - self.position # rotate this vector into the CS of the magnet (inverse rotation) rotatedPos = angleAxisRotation_priv(self.angle, -self.axis, posRel) # pylint: disable=invalid-unary-operand-type # rotate field vector back BCm = angleAxisRotation_priv(self.angle, self.axis, Bfield_CircularCurrentLoop(self.current,self.dimension,rotatedPos)) # BCm is the obtained magnetic field in Cm # the field is well known in the magnet coordinates. return BCm
def __repr__(self): """ This is for the IPython Console When you call a defined circular, this method shows you all its components. Examples -------- >>> from magpylib import source >>> c = source.current.Circular(2.45, 3.1469, [4.4, 5.24, 0.5]) >>> c type: current.Circular current: 2.45 dimension: d: 3.1469 position: x: 4.4, y: 5.24, z: 0.5 angle: 0.0 axis: x: 0.0, y: 0.0, z: 1.0 """ return "type: {} \n current: {} \n dimension: d: {} \n position: x: {}, y: {}, z: {} \n angle: {} \n axis: x: {}, y: {}, z: {}".format("current.Circular", self.current, self.dimension, *self.position, self.angle, *self.axis)
# -------------------------------------------------------------------------------
[docs]class Line(LineCurrent): """ A line current flowing along linear segments from vertex to vertex given by a list of positions `vertices` in the canonical basis (position=[0,0,0], angle=0.0, axis=[0,0,1]). Scalar input is either integer or float. Vector input format can be either list, tuple or array of any data type (float, int). Parameters ---------- curr : scalar [A] Set current in loop in units of [A] vertices : vecNx3 [mm] N positions given in units of [mm] that make up N-1 linear segments along which the current `curr` flows, starting from the first position and ending with the last one. [[x,y,z], [x,y,z], ...] "[pos1,pos2,...]" pos=[0,0,0] : vec3 [mm] Set reference position of the current distribution in units of [mm]. angle=0.0 : scalar [deg] Set angle of orientation of current distribution in units of [deg]. axis=[0,0,1] : vec3 [] Set axis of orientation of the current distribution. Attributes ---------- current : float [A] Current flowing along line in units of [A]. vertices : arrNx3 [mm] Positions of line current vertices in units of [mm]. position : arr3 [mm] Reference position of line current in units of [mm]. angle : float [deg] Angle of orientation of line current in units of [deg]. axis : arr3 [] Axis of orientation of the line current. Examples -------- >>> from magpylib import source >>> from numpy import sin,cos,pi,linspace >>> vertices = [[cos(phi),sin(phi),0] for phi in linspace(0,2*pi,36)] >>> cd = source.current.Line(curr=10,vertices=vertices) >>> B = cd.getB([0,0,2]) >>> print(B) [-6.24500451e-17 1.73472348e-18 5.59871233e-01] Note ---- The following Methods are available to all sources objects. """ def __init__(self, curr=I, vertices=listOfPos, pos=(0.0, 0.0, 0.0), angle=0.0, axis=(0.0, 0.0, 1.0)): # inherit class lineCurrent # - pos, Mrot, MrotInv, curr # - moveBy, rotateBy LineCurrent.__init__(self, pos, angle, axis, curr) # secure input type and check input format of dim assert isinstance(vertices, list) or isinstance( vertices, ndarray), 'Line Current: enter a list of position vertices - Ex: Line(vertices=[(1,2,3),(3,2,1)])' assert all(isinstance(pos, tuple) or isinstance(pos, list) or isinstance(pos, ndarray) for pos in vertices), 'Line-current: Input position (3D) tuples or lists within the list - Ex: Line(vertices=[(1,2,3),(3,2,1)])' assert all(len( d) == 3 for d in vertices), 'Line-current: Bad input dimension, vectors in list must be 3D' self.vertices = array(vertices, dtype=float64, copy=False)
[docs] def getB(self, pos): # Particular Line current B field calculation. Check RCS for getB() interface # vectorized code if input is an Nx3 array if type(pos) == ndarray: if len(shape(pos))==2: # list of positions - use vectorized code # vector size NN = shape(pos)[0] # prepare vector inputs POSREL = pos - self.position ANG = ones(NN)*self.angle AX = tile(self.axis,(NN,1)) # compute rotations and field ROTATEDPOS = angleAxisRotationV_priv(ANG, -AX, POSREL) BB = Bfield_CurrentLineVV(self.vertices,self.current,ROTATEDPOS) BCM = angleAxisRotationV_priv(ANG, AX, BB) return BCM # secure input type and check input format p1 = array(pos, dtype=float64, copy=False) # relative position between mag and obs posRel = p1 - self.position # rotate this vector into the CS of the magnet (inverse rotation) rotatedPos = angleAxisRotation_priv(self.angle, -self.axis, posRel) # pylint: disable=invalid-unary-operand-type # rotate field vector back BCm = angleAxisRotation_priv(self.angle, self.axis, Bfield_CurrentLineV(self.vertices, self.current,rotatedPos)) # BCm is the obtained magnetic field in Cm # the field is well known in the magnet coordinates. return BCm
def __repr__(self): """ This is for the IPython Console When you call a defined line, this method shows you all its components. Examples -------- >>> from magpylib import source >>> l = source.current.Line(2.45, [[2, .35, 2], [10, 2, -4], [4, 2, 1], [102, 2, 7]], [4.4, 5.24, 0.5]) >>> l type: current.Line current: 2.45 dimensions: vertices position: x: 4.4, y: 5.24, z: 0.5 angle: 0.0 axis: x: 0.0, y: 0.0, z: 1.0 """ return "type: {} \n current: {} \n dimensions: vertices \n position: x: {}, y: {}, z: {} \n angle: {} \n axis: x: {}, y: {}, z: {}".format("current.Line", self.current, *self.position, self.angle, *self.axis)