25
25
from numpy import array , NaN
26
26
from magpylib ._lib .mathLib import fastSum3D , fastNorm3D , fastCross3D
27
27
from warnings import warn
28
+ import numpy as np
29
+ from numpy .linalg import norm
28
30
29
31
# %% CURRENT LINE
30
32
# Describes the magnetic field of a line current. The line is given by a set of
38
40
# source: http://www.phys.uri.edu/gerhard/PHY204/tsl216.pdf
39
41
# FieldOfLineCurrent
40
42
43
+ # VECTORIZED VERSION
44
+ # here we only use vectorized code as this function will primarily be
45
+ # used to call on multiple line segments. The vectorized code was
46
+ # developed based on the depreciated version below.
47
+
48
+ def Bfield_LineSegmentV (p0 , p1 , p2 , I0 ):
49
+ ''' private
50
+ base function determines the fields of given line segments
51
+ p0 = observer position
52
+ p1->p2 = current flows from vertex p1 to vertex p2
53
+ I0 = current in [A]
54
+ '''
55
+
56
+ N = len (p0 )
57
+ fields = np .zeros ((N ,3 )) # default values for mask0 and mask1
58
+
59
+ # Check for zero-length segment
60
+ mask0 = np .all (p1 == p2 ,axis = 1 )
61
+
62
+ # projection of p0 onto line p1-p2
63
+ nm0 = np .invert (mask0 )
64
+ p1p2 = (p1 [nm0 ]- p2 [nm0 ])
65
+ p4 = p1 [nm0 ]+ (p1p2 .T * np .sum ((p0 [nm0 ]- p1 [nm0 ])* p1p2 ,axis = 1 )/ np .sum (p1p2 ** 2 ,axis = 1 )).T
66
+
67
+ # determine anchorrect normal vector to surface spanned by triangle
68
+ cross0 = np .cross (- p1p2 , p0 [nm0 ]- p4 )
69
+ norm_cross0 = norm (cross0 ,axis = 1 )
70
+
71
+ # on-line cases (include when position is on current path)
72
+ mask1 = (norm_cross0 == 0 )
73
+
74
+ # normal cases
75
+ nm1 = np .invert (mask1 )
76
+ eB = (cross0 [nm1 ].T / norm_cross0 [nm1 ]) #field direction
77
+
78
+ # not mask0 and not mask1
79
+ NM = np .copy (nm0 )
80
+ NM [NM == True ] = nm1
81
+
82
+ norm_04 = norm (p0 [NM ] - p4 [nm1 ],axis = 1 )
83
+ norm_01 = norm (p0 [NM ] - p1 [NM ],axis = 1 )
84
+ norm_02 = norm (p0 [NM ] - p2 [NM ],axis = 1 )
85
+ norm_12 = norm (p1 [NM ] - p2 [NM ],axis = 1 )
86
+ norm_41 = norm (p4 [nm1 ]- p1 [NM ],axis = 1 )
87
+ norm_42 = norm (p4 [nm1 ]- p2 [NM ],axis = 1 )
88
+
89
+ sinTh1 = norm_41 / norm_01
90
+ sinTh2 = norm_42 / norm_02
91
+
92
+ deltaSin = np .empty ((N ))[NM ]
93
+
94
+ # determine how p1,p2,p4 are sorted on the line (to get sinTH signs)
95
+ # both points below
96
+ mask2 = ((norm_41 > norm_12 ) * (norm_41 > norm_42 ))
97
+ deltaSin [mask2 ] = abs (sinTh1 [mask2 ]- sinTh2 [mask2 ])
98
+ # both points above
99
+ mask3 = ((norm_42 > norm_12 ) * (norm_42 > norm_41 ))
100
+ deltaSin [mask3 ] = abs (sinTh2 [mask3 ]- sinTh1 [mask3 ])
101
+ # one above one below or one equals p4
102
+ mask4 = np .invert (mask2 )* np .invert (mask3 )
103
+ deltaSin [mask4 ] = abs (sinTh1 [mask4 ]+ sinTh2 [mask4 ])
104
+
105
+ # missing 10**-6 from m->mm conversion #T->mT conversion
106
+ fields [NM ] = (I0 [NM ]* deltaSin / norm_04 * eB ).T / 10
107
+
108
+ return fields
109
+
110
+
111
+
112
+ def Bfield_CurrentLineV (VERT ,i0 ,poso ):
113
+ ''' private
114
+ determine total field from a multi-segment line current
115
+ '''
116
+
117
+ N = len (VERT )- 1
118
+ P0 = np .outer (np .ones ((N )),poso )
119
+ P1 = VERT [:- 1 ]
120
+ P2 = VERT [1 :]
121
+ I0 = np .ones ((N ))* i0
122
+
123
+ Bv = Bfield_LineSegmentV (P0 ,P1 ,P2 ,I0 )
124
+
125
+ return np .sum (Bv ,axis = 0 )
126
+
127
+
128
+
129
+
130
+
131
+ ''' DEPRECHIATED VERSION (non-vectorized)
132
+
41
133
# observer at p0
42
134
# current I0 flows in straight line from p1 to p2
43
135
def Bfield_LineSegment(p0, p1, p2, I0):
@@ -90,15 +182,4 @@ def Bfield_LineSegment(p0, p1, p2, I0):
90
182
B = I0*deltaSin/norm_04*eB/10
91
183
92
184
return B
93
-
94
- # determine total field from multiple segments
95
-
96
-
97
- def Bfield_CurrentLine (p0 , possis , I0 ):
98
-
99
- B = array ([0. , 0. , 0. ])
100
- for i in range (len (possis )- 1 ):
101
- p1 = possis [i ]
102
- p2 = possis [i + 1 ]
103
- B += Bfield_LineSegment (p0 , p1 , p2 , I0 )
104
- return B
185
+ '''
0 commit comments