def laplacian(expr): """ Return the laplacian of the given field computed in terms of the base scalars of the given coordinate system. Parameters ========== expr : SymPy Expr or Vector expr denotes a scalar or vector field. Examples ======== >>> from sympy.vector import CoordSys3D, laplacian >>> R = CoordSys3D('R') >>> f = R.x**2*R.y**5*R.z >>> laplacian(f) 20*R.x**2*R.y**3*R.z + 2*R.y**5*R.z >>> f = R.x**2*R.i + R.y**3*R.j + R.z**4*R.k >>> laplacian(f) 2*R.i + 6*R.y*R.j + 12*R.z**2*R.k """ delop = Del() if expr.is_Vector: return (gradient(divergence(expr)) - curl(curl(expr))).doit() return delop.dot(delop(expr)).doit()
def delop(self): SymPyDeprecationWarning( feature="coord_system.delop has been replaced.", useinstead="Use the Del() class", deprecated_since_version="1.1", issue=12866, ).warn() from sympy.vector.deloperator import Del return Del()
def __new__(cls, name, location=None, rotation_matrix=None, parent=None, vector_names=None, variable_names=None): """ The orientation/location parameters are necessary if this system is being defined at a certain orientation or location wrt another. Parameters ========== name : str The name of the new CoordSysCartesian instance. location : Vector The position vector of the new system's origin wrt the parent instance. rotation_matrix : SymPy ImmutableMatrix The rotation matrix of the new coordinate system with respect to the parent. In other words, the output of new_system.rotation_matrix(parent). parent : CoordSysCartesian The coordinate system wrt which the orientation/location (or both) is being defined. vector_names, variable_names : iterable(optional) Iterables of 3 strings each, with custom names for base vectors and base scalars of the new system respectively. Used for simple str printing. """ name = str(name) Vector = sympy.vector.Vector BaseVector = sympy.vector.BaseVector Point = sympy.vector.Point if not isinstance(name, string_types): raise TypeError("name should be a string") #If orientation information has been provided, store #the rotation matrix accordingly if rotation_matrix is None: parent_orient = Matrix(eye(3)) else: if not isinstance(rotation_matrix, Matrix): raise TypeError("rotation_matrix should be an Immutable" + "Matrix instance") parent_orient = rotation_matrix #If location information is not given, adjust the default #location as Vector.zero if parent is not None: if not isinstance(parent, CoordSysCartesian): raise TypeError("parent should be a " + "CoordSysCartesian/None") if location is None: location = Vector.zero else: if not isinstance(location, Vector): raise TypeError("location should be a Vector") #Check that location does not contain base #scalars for x in location.free_symbols: if isinstance(x, BaseScalar): raise ValueError("location should not contain" + " BaseScalars") origin = parent.origin.locate_new(name + '.origin', location) else: location = Vector.zero origin = Point(name + '.origin') #All systems that are defined as 'roots' are unequal, unless #they have the same name. #Systems defined at same orientation/position wrt the same #'parent' are equal, irrespective of the name. #This is true even if the same orientation is provided via #different methods like Axis/Body/Space/Quaternion. #However, coincident systems may be seen as unequal if #positioned/oriented wrt different parents, even though #they may actually be 'coincident' wrt the root system. if parent is not None: obj = super(CoordSysCartesian, cls).__new__(cls, Symbol(name), location, parent_orient, parent) else: obj = super(CoordSysCartesian, cls).__new__(cls, Symbol(name), location, parent_orient) obj._name = name #Initialize the base vectors if vector_names is None: vector_names = (name + '.i', name + '.j', name + '.k') latex_vects = [(r'\mathbf{\hat{i}_{%s}}' % name), (r'\mathbf{\hat{j}_{%s}}' % name), (r'\mathbf{\hat{k}_{%s}}' % name)] pretty_vects = (name + '_i', name + '_j', name + '_k') else: _check_strings('vector_names', vector_names) vector_names = list(vector_names) latex_vects = [(r'\mathbf{\hat{%s}_{%s}}' % (x, name)) for x in vector_names] pretty_vects = [(name + '_' + x) for x in vector_names] obj._i = BaseVector(vector_names[0], 0, obj, pretty_vects[0], latex_vects[0]) obj._j = BaseVector(vector_names[1], 1, obj, pretty_vects[1], latex_vects[1]) obj._k = BaseVector(vector_names[2], 2, obj, pretty_vects[2], latex_vects[2]) #Initialize the base scalars if variable_names is None: variable_names = (name + '.x', name + '.y', name + '.z') latex_scalars = [(r"\mathbf{{x}_{%s}}" % name), (r"\mathbf{{y}_{%s}}" % name), (r"\mathbf{{z}_{%s}}" % name)] pretty_scalars = (name + '_x', name + '_y', name + '_z') else: _check_strings('variable_names', vector_names) variable_names = list(variable_names) latex_scalars = [(r"\mathbf{{%s}_{%s}}" % (x, name)) for x in variable_names] pretty_scalars = [(name + '_' + x) for x in variable_names] obj._x = BaseScalar(variable_names[0], 0, obj, pretty_scalars[0], latex_scalars[0]) obj._y = BaseScalar(variable_names[1], 1, obj, pretty_scalars[1], latex_scalars[1]) obj._z = BaseScalar(variable_names[2], 2, obj, pretty_scalars[2], latex_scalars[2]) #Assign a Del operator instance from sympy.vector.deloperator import Del obj._delop = Del(obj) #Assign params obj._parent = parent if obj._parent is not None: obj._root = obj._parent._root else: obj._root = obj obj._parent_rotation_matrix = parent_orient obj._origin = origin #Return the instance return obj
) from sympy.vector.deloperator import Del from sympy.vector.functions import ( is_conservative, is_solenoidal, scalar_potential, directional_derivative, laplacian, scalar_potential_difference, ) from sympy.testing.pytest import raises C = CoordSys3D("C") i, j, k = C.base_vectors() x, y, z = C.base_scalars() delop = Del() a, b, c, q = symbols("a b c q") def test_del_operator(): # Tests for curl assert delop ^ Vector.zero == Vector.zero assert (delop ^ Vector.zero).doit() == Vector.zero == curl(Vector.zero) assert delop.cross(Vector.zero) == delop ^ Vector.zero assert (delop ^ i).doit() == Vector.zero assert delop.cross(2 * y ** 2 * j, doit=True) == Vector.zero assert delop.cross(2 * y ** 2 * j) == delop ^ 2 * y ** 2 * j v = x * y * z * (i + j + k) assert ( (delop ^ v).doit()
def __new__(cls, name, vector_names=None, variable_names=None, location=None, rot_type=None, rot_amounts=None, rot_order='', parent=None): """ The orientation/location parameters are necessary if this system is being defined at a certain orientation or location wrt another. For more information on the orientation parameters, please refer to the docs of orient_new method. Parameters ========== name : str The name of the new CoordSysCartesian instance. vector_names, variable_names : tuples/lists(optional) Tuples/Lists of 3 strings each, with custom names for base vectors and base scalars of the new system respectively. location : Vector The position vector of the new system's origin wrt the parent instance. rot_type : str ('Axis'/'Body'/'Quaternion'/'Space') The type of orientation matrix that is being created. rot_amounts : list OR value The quantities that the orientation matrix will be defined by. rot_order : str (Look at the docs of orient_new for more details) If applicable, the order of a series of rotations. parent : CoordSysCartesian The coordinate system wrt which the orientation/location (or both) is being defined. docstring of orient_new ======================= """ if not isinstance(name, string_types): raise TypeError("name should be a string") #If orientation information has been provided, calculate #the DCM accordingly from sympy.vector.vector import BaseVector, Vector if rot_type is not None: for i, v in enumerate(rot_amounts): if not isinstance(v, Vector): rot_amounts[i] = sympify(v) rot_type = rot_type.upper() if rot_type == 'AXIS': parent_orient = _orient_axis(list(rot_amounts), rot_order, parent) elif rot_type == 'QUATERNION': parent_orient = _orient_quaternion(list(rot_amounts), rot_order) elif rot_type == 'BODY': parent_orient = _orient_body(list(rot_amounts), rot_order) elif rot_type == 'SPACE': parent_orient = _orient_space(list(rot_amounts), rot_order) else: raise NotImplementedError('Rotation not implemented') else: if not (rot_amounts == None and rot_order == ''): raise ValueError("No rotation type provided") parent_orient = Matrix(eye(3)) #If location information is not given, adjust the default #location as Vector.zero from sympy.vector.point import Point if parent is not None: if not isinstance(parent, CoordSysCartesian): raise TypeError("parent should be a " + "CoordSysCartesian/None") if location is None: location = Vector.zero origin = parent.origin.locate_new(name + '.origin', location) arg_parent = parent arg_self = Symbol('default') else: origin = Point(name + '.origin') arg_parent = Symbol('default') arg_self = Symbol(name) #All systems that are defined as 'roots' are unequal, unless #they have the same name. #Systems defined at same orientation/position wrt the same #'parent' are equal, irrespective of the name. #This is true even if the same orientation is provided via #different methods like Axis/Body/Space/Quaternion. #However, coincident systems may be seen as unequal if #positioned/oriented wrt different parents, even though #they may actually be 'coincident' wrt the root system. obj = super(CoordSysCartesian, cls).__new__(cls, arg_self, parent_orient, origin, arg_parent) obj._name = name #Initialize the base vectors if vector_names is None: vector_names = (name + '.i', name + '.j', name + '.k') obj._i = BaseVector(vector_names[0], 0, obj) obj._j = BaseVector(vector_names[1], 1, obj) obj._k = BaseVector(vector_names[2], 2, obj) #Initialize the base scalars if variable_names is None: variable_names = (name + '.x', name + '.y', name + '.z') obj._x = BaseScalar(variable_names[0], 0, obj) obj._y = BaseScalar(variable_names[1], 1, obj) obj._z = BaseScalar(variable_names[2], 2, obj) #Assign a Del operator instance from sympy.vector.deloperator import Del obj._del = Del(obj) #Assign params obj._parent = parent if obj._parent is not None: obj._root = obj._parent._root else: obj._root = obj obj._parent_rotation_matrix = parent_orient.T obj._origin = origin #Return the instance return obj