switching to high quality piper tts and added label translations
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
from sympy.core import Basic, diff
|
||||
from sympy.core.singleton import S
|
||||
from sympy.core.sorting import default_sort_key
|
||||
from sympy.matrices import Matrix
|
||||
from sympy.integrals import Integral, integrate
|
||||
from sympy.geometry.entity import GeometryEntity
|
||||
from sympy.simplify.simplify import simplify
|
||||
from sympy.utilities.iterables import topological_sort
|
||||
from sympy.vector import (CoordSys3D, Vector, ParametricRegion,
|
||||
parametric_region_list, ImplicitRegion)
|
||||
from sympy.vector.operators import _get_coord_systems
|
||||
|
||||
|
||||
class ParametricIntegral(Basic):
|
||||
"""
|
||||
Represents integral of a scalar or vector field
|
||||
over a Parametric Region
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
>>> from sympy import cos, sin, pi
|
||||
>>> from sympy.vector import CoordSys3D, ParametricRegion, ParametricIntegral
|
||||
>>> from sympy.abc import r, t, theta, phi
|
||||
|
||||
>>> C = CoordSys3D('C')
|
||||
>>> curve = ParametricRegion((3*t - 2, t + 1), (t, 1, 2))
|
||||
>>> ParametricIntegral(C.x, curve)
|
||||
5*sqrt(10)/2
|
||||
>>> length = ParametricIntegral(1, curve)
|
||||
>>> length
|
||||
sqrt(10)
|
||||
>>> semisphere = ParametricRegion((2*sin(phi)*cos(theta), 2*sin(phi)*sin(theta), 2*cos(phi)),\
|
||||
(theta, 0, 2*pi), (phi, 0, pi/2))
|
||||
>>> ParametricIntegral(C.z, semisphere)
|
||||
8*pi
|
||||
|
||||
>>> ParametricIntegral(C.j + C.k, ParametricRegion((r*cos(theta), r*sin(theta)), r, theta))
|
||||
0
|
||||
|
||||
"""
|
||||
|
||||
def __new__(cls, field, parametricregion):
|
||||
|
||||
coord_set = _get_coord_systems(field)
|
||||
|
||||
if len(coord_set) == 0:
|
||||
coord_sys = CoordSys3D('C')
|
||||
elif len(coord_set) > 1:
|
||||
raise ValueError
|
||||
else:
|
||||
coord_sys = next(iter(coord_set))
|
||||
|
||||
if parametricregion.dimensions == 0:
|
||||
return S.Zero
|
||||
|
||||
base_vectors = coord_sys.base_vectors()
|
||||
base_scalars = coord_sys.base_scalars()
|
||||
|
||||
parametricfield = field
|
||||
|
||||
r = Vector.zero
|
||||
for i in range(len(parametricregion.definition)):
|
||||
r += base_vectors[i]*parametricregion.definition[i]
|
||||
|
||||
if len(coord_set) != 0:
|
||||
for i in range(len(parametricregion.definition)):
|
||||
parametricfield = parametricfield.subs(base_scalars[i], parametricregion.definition[i])
|
||||
|
||||
if parametricregion.dimensions == 1:
|
||||
parameter = parametricregion.parameters[0]
|
||||
|
||||
r_diff = diff(r, parameter)
|
||||
lower, upper = parametricregion.limits[parameter][0], parametricregion.limits[parameter][1]
|
||||
|
||||
if isinstance(parametricfield, Vector):
|
||||
integrand = simplify(r_diff.dot(parametricfield))
|
||||
else:
|
||||
integrand = simplify(r_diff.magnitude()*parametricfield)
|
||||
|
||||
result = integrate(integrand, (parameter, lower, upper))
|
||||
|
||||
elif parametricregion.dimensions == 2:
|
||||
u, v = cls._bounds_case(parametricregion.parameters, parametricregion.limits)
|
||||
|
||||
r_u = diff(r, u)
|
||||
r_v = diff(r, v)
|
||||
normal_vector = simplify(r_u.cross(r_v))
|
||||
|
||||
if isinstance(parametricfield, Vector):
|
||||
integrand = parametricfield.dot(normal_vector)
|
||||
else:
|
||||
integrand = parametricfield*normal_vector.magnitude()
|
||||
|
||||
integrand = simplify(integrand)
|
||||
|
||||
lower_u, upper_u = parametricregion.limits[u][0], parametricregion.limits[u][1]
|
||||
lower_v, upper_v = parametricregion.limits[v][0], parametricregion.limits[v][1]
|
||||
|
||||
result = integrate(integrand, (u, lower_u, upper_u), (v, lower_v, upper_v))
|
||||
|
||||
else:
|
||||
variables = cls._bounds_case(parametricregion.parameters, parametricregion.limits)
|
||||
coeff = Matrix(parametricregion.definition).jacobian(variables).det()
|
||||
integrand = simplify(parametricfield*coeff)
|
||||
|
||||
l = [(var, parametricregion.limits[var][0], parametricregion.limits[var][1]) for var in variables]
|
||||
result = integrate(integrand, *l)
|
||||
|
||||
if not isinstance(result, Integral):
|
||||
return result
|
||||
else:
|
||||
return super().__new__(cls, field, parametricregion)
|
||||
|
||||
@classmethod
|
||||
def _bounds_case(cls, parameters, limits):
|
||||
|
||||
V = list(limits.keys())
|
||||
E = []
|
||||
|
||||
for p in V:
|
||||
lower_p = limits[p][0]
|
||||
upper_p = limits[p][1]
|
||||
|
||||
lower_p = lower_p.atoms()
|
||||
upper_p = upper_p.atoms()
|
||||
E.extend((p, q) for q in V if p != q and
|
||||
(lower_p.issuperset({q}) or upper_p.issuperset({q})))
|
||||
|
||||
if not E:
|
||||
return parameters
|
||||
else:
|
||||
return topological_sort((V, E), key=default_sort_key)
|
||||
|
||||
@property
|
||||
def field(self):
|
||||
return self.args[0]
|
||||
|
||||
@property
|
||||
def parametricregion(self):
|
||||
return self.args[1]
|
||||
|
||||
|
||||
def vector_integrate(field, *region):
|
||||
"""
|
||||
Compute the integral of a vector/scalar field
|
||||
over a a region or a set of parameters.
|
||||
|
||||
Examples
|
||||
========
|
||||
>>> from sympy.vector import CoordSys3D, ParametricRegion, vector_integrate
|
||||
>>> from sympy.abc import x, y, t
|
||||
>>> C = CoordSys3D('C')
|
||||
|
||||
>>> region = ParametricRegion((t, t**2), (t, 1, 5))
|
||||
>>> vector_integrate(C.x*C.i, region)
|
||||
12
|
||||
|
||||
Integrals over some objects of geometry module can also be calculated.
|
||||
|
||||
>>> from sympy.geometry import Point, Circle, Triangle
|
||||
>>> c = Circle(Point(0, 2), 5)
|
||||
>>> vector_integrate(C.x**2 + C.y**2, c)
|
||||
290*pi
|
||||
>>> triangle = Triangle(Point(-2, 3), Point(2, 3), Point(0, 5))
|
||||
>>> vector_integrate(3*C.x**2*C.y*C.i + C.j, triangle)
|
||||
-8
|
||||
|
||||
Integrals over some simple implicit regions can be computed. But in most cases,
|
||||
it takes too long to compute over them. This is due to the expressions of parametric
|
||||
representation becoming large.
|
||||
|
||||
>>> from sympy.vector import ImplicitRegion
|
||||
>>> c2 = ImplicitRegion((x, y), (x - 2)**2 + (y - 1)**2 - 9)
|
||||
>>> vector_integrate(1, c2)
|
||||
6*pi
|
||||
|
||||
Integral of fields with respect to base scalars:
|
||||
|
||||
>>> vector_integrate(12*C.y**3, (C.y, 1, 3))
|
||||
240
|
||||
>>> vector_integrate(C.x**2*C.z, C.x)
|
||||
C.x**3*C.z/3
|
||||
>>> vector_integrate(C.x*C.i - C.y*C.k, C.x)
|
||||
(Integral(C.x, C.x))*C.i + (Integral(-C.y, C.x))*C.k
|
||||
>>> _.doit()
|
||||
C.x**2/2*C.i + (-C.x*C.y)*C.k
|
||||
|
||||
"""
|
||||
if len(region) == 1:
|
||||
if isinstance(region[0], ParametricRegion):
|
||||
return ParametricIntegral(field, region[0])
|
||||
|
||||
if isinstance(region[0], ImplicitRegion):
|
||||
region = parametric_region_list(region[0])[0]
|
||||
return vector_integrate(field, region)
|
||||
|
||||
if isinstance(region[0], GeometryEntity):
|
||||
regions_list = parametric_region_list(region[0])
|
||||
|
||||
result = 0
|
||||
for reg in regions_list:
|
||||
result += vector_integrate(field, reg)
|
||||
return result
|
||||
|
||||
return integrate(field, *region)
|
||||
Reference in New Issue
Block a user