def Test_Reciprocal_Frame(): Print_Function() coords = symbols('x y z') (ex, ey, ez, grad) = MV.setup('ex ey ez', metric='[1,1,1]', coords=coords) mfvar = (u, v) = symbols('u v') eu = ex + ey ev = ex - ey (eu_r, ev_r) = ReciprocalFrame([eu, ev]) oprint('Frame', (eu, ev), 'Reciprocal Frame', (eu_r, ev_r)) print('eu.eu_r =', eu | eu_r) print('eu.ev_r =', eu | ev_r) print('ev.eu_r =', ev | eu_r) print('ev.ev_r =', ev | ev_r) eu = ex + ey + ez ev = ex - ey (eu_r, ev_r) = ReciprocalFrame([eu, ev]) oprint('Frame', (eu, ev), 'Reciprocal Frame', (eu_r, ev_r)) print('eu.eu_r =', eu | eu_r) print('eu.ev_r =', eu | ev_r) print('ev.eu_r =', ev | eu_r) print('ev.ev_r =', ev | ev_r) return
def setup(base, n=None, metric=None, coords=None, curv=(None, None), debug=False): """ Generate basis of vector space as tuple of vectors and associated metric tensor as Matrix. See str_array(base,n) for usage of base and n and str_array(metric) for usage of metric. To overide elements in the default metric use the character '#' in the metric string. For example if one wishes the diagonal elements of the metric tensor to be zero enter metric = '0 #,# 0'. If the basis vectors are e1 and e2 then the default metric - Vector.metric = ((dot(e1,e1),dot(e1,e2)),dot(e2,e1),dot(e2,e2)) becomes - Vector.metric = ((0,dot(e1,e2)),(dot(e2,e1),0)). The function dot returns a Symbol and is symmetric. The functions 'Bases' calculates the global quantities: - Vector.basis tuple of basis vectors Vector.base_to_index dictionary to convert base to base inded Vector.metric metric tensor represented as a matrix of symbols and numbers """ Vector.is_orthogonal = False Vector.coords = coords Vector.subscripts = [] base_name_lst = base.split(' ') # Define basis vectors if '*' in base: base_lst = base.split('*') base = base_lst[0] Vector.subscripts = base_lst[1].split('|') base_name_lst = [] for subscript in Vector.subscripts: base_name_lst.append(base + '_' + subscript) else: if len(base_name_lst) > 1: Vector.subscripts = [] for base_name in base_name_lst: tmp = base_name.split('_') Vector.subscripts.append(tmp[-1]) elif len(base_name_lst) == 1 and Vector.coords is not None: base_name_lst = [] for coord in Vector.coords: Vector.subscripts.append(str(coord)) base_name_lst.append(base + '_' + str(coord)) else: raise TypeError("'%s' does not define basis vectors" % base) basis = [] base_to_index = {} index = 0 for base_name in base_name_lst: basis_vec = Vector(base_name) basis.append(basis_vec) base_to_index[basis_vec.obj] = index index += 1 Vector.base_to_index = base_to_index Vector.basis = tuple(basis) # define metric tensor default_metric = [] for bv1 in Vector.basis: row = [] for bv2 in Vector.basis: row.append(Vector.basic_dot(bv1, bv2)) default_metric.append(row) Vector.metric = Matrix(default_metric) if metric is not None: if metric[0] == '[' and metric[-1] == ']': Vector.is_orthogonal = True metric_str_lst = metric[1:-1].split(',') Vector.metric = [] for g_ii in metric_str_lst: Vector.metric.append(S(g_ii)) Vector.metric = Matrix(Vector.metric) else: metric_str_lst = flatten(str_array(metric)) for index in range(len(metric_str_lst)): if metric_str_lst[index] != '#': Vector.metric[index] = S(metric_str_lst[index]) Vector.metric_dict = {} # Used to calculate dot product N = range(len(Vector.basis)) if Vector.is_orthogonal: for ii in N: Vector.metric_dict[Vector.basis[ii].obj] = Vector.metric[ii] else: for irow in N: for icol in N: Vector.metric_dict[(Vector.basis[irow].obj, Vector.basis[icol].obj)] = Vector.metric[irow, icol] # calculate tangent vectors and metric for curvilinear basis if curv != (None, None): X = S.Zero for (coef, base) in zip(curv[0], Vector.basis): X += coef * base.obj Vector.tangents = [] for (coord, norm) in zip(Vector.coords, curv[1]): tau = diff(X, coord) tau = trigsimp(tau) tau /= norm tau = expand(tau) Vtau = Vector() Vtau.obj = tau Vector.tangents.append(Vtau) metric = [] for tv1 in Vector.tangents: row = [] for tv2 in Vector.tangents: row.append(tv1 * tv2) metric.append(row) metric = Matrix(metric) metric = metric.applyfunc(TrigSimp) Vector.metric_dict = {} if metric.is_diagonal: Vector.is_orthogonal = True tmp_metric = [] for ii in N: tmp_metric.append(metric[ii, ii]) Vector.metric_dict[Vector.basis[ii].obj] = metric[ii, ii] Vector.metric = Matrix(tmp_metric) else: Vector.is_orthogonal = False Vector.metric = metric for irow in N: for icol in N: Vector.metric_dict[(Vector.basis[irow].obj, Vector.basis[icol].obj)] = Vector.metric[irow, icol] Vector.norm = curv[1] if debug: oprint('Tangent Vectors', Vector.tangents, 'Metric', Vector.metric, 'Metric Dictionary', Vector.metric_dict, 'Normalization', Vector.norm, dict_mode=True) # calculate derivatives of tangent vectors Vector.dtau_dict = None dtau_dict = {} for x in Vector.coords: for (tau, base) in zip(Vector.tangents, Vector.basis): dtau = tau.diff(x).applyfunc(TrigSimp) result = S.Zero for (t, b) in zip(Vector.tangents, Vector.basis): t_dtau = TrigSimp(t * dtau) result += t_dtau * b.obj dtau_dict[(base.obj, x)] = result Vector.dtau_dict = dtau_dict if debug: oprint('Basis Derivatives', Vector.dtau_dict, dict_mode=True) return tuple(Vector.basis)
def __init__(self, x, coords, debug=False, I=None): """ coords: list of coordinate variables x: vector fuction of coordinate variables (parametric surface) """ self.I = I self.x = x self.coords = coords self.basis = [] self.basis_str = [] self.embedded_basis = [] for u in coords: tv = x.diff(u) self.basis.append(tv) (coefs, bases) = linear_expand(tv.obj) tc = {} for (coef, base) in zip(coefs, bases): str_base = str(base) tc[str_base] = coef if str_base not in self.embedded_basis: self.embedded_basis.append(str_base) self.basis_str.append(tc) self.gij = [] for base1 in self.basis: tmp = [] for base2 in self.basis: tmp.append(simplify(trigsimp((base1 | base2).scalar()))) self.gij.append(tmp) for tv in self.basis_str: for base in self.embedded_basis: if base not in tv: tv[base] = 0 self.dim = len(self.basis) indexes = tuple(range(self.dim)) self.index = [()] for i in indexes: self.index.append(tuple(combinations(indexes, i + 1))) self.index = tuple(self.index) self.MFbasis = [[MV.ONE], self.basis] for igrade in self.index[2:]: grade = [] for iblade in igrade: blade = MV(1, 'scalar') for ibasis in iblade: blade ^= self.basis[ibasis] blade = blade.trigsimp(deep=True, recursive=True) grade.append(blade) self.MFbasis.append(grade) self.E = self.MFbasis[-1][0] self.E_sq = trigsimp((self.E * self.E).scalar(), deep=True, recursive=True) duals = copy.copy(self.MFbasis[-2]) duals.reverse() sgn = 1 self.rbasis = [] for dual in duals: recpv = (sgn * dual * self.E).trigsimp(deep=True, recursive=True) self.rbasis.append(recpv) sgn = -sgn self.dbasis = [] for base in self.basis: dbase = [] for coord in self.coords: d = base.diff(coord).trigsimp(deep=True, recursive=True) dbase.append(d) self.dbasis.append(dbase) self.surface = {} (coefs, bases) = linear_expand(self.x.obj) for (coef, base) in zip(coefs, bases): self.surface[str(base)] = coef self.grad = MV() self.grad.is_grad = True self.grad.blade_rep = True self.grad.igrade = 1 self.grad.rcpr_bases_MV = [] for rbase in self.rbasis: self.grad.rcpr_bases_MV.append(rbase / self.E_sq) self.grad.rcpr_bases_MV = tuple(self.grad.rcpr_bases_MV) self.grad.coords = self.coords self.grad.norm = self.E_sq self.grad.connection = {} if debug: oprint('x', self.x, 'coords', self.coords, 'basis vectors', self.basis, 'index', self.index, 'basis blades', self.MFbasis, 'E', self.E, 'E**2', self.E_sq, '*basis', duals, 'rbasis', self.rbasis, 'basis derivatives', self.dbasis, 'surface', self.surface, 'basis strings', self.basis_str, 'embedding basis', self.embedded_basis, 'metric tensor', self.gij)
def setup(base, n=None, metric=None, coords=None, curv=(None, None), debug=False): """ Generate basis of vector space as tuple of vectors and associated metric tensor as Matrix. See str_array(base,n) for usage of base and n and str_array(metric) for usage of metric. To overide elements in the default metric use the character '#' in the metric string. For example if one wishes the diagonal elements of the metric tensor to be zero enter metric = '0 #,# 0'. If the basis vectors are e1 and e2 then the default metric - Vector.metric = ((dot(e1,e1),dot(e1,e2)),dot(e2,e1),dot(e2,e2)) becomes - Vector.metric = ((0,dot(e1,e2)),(dot(e2,e1),0)). The function dot returns a Symbol and is symmetric. The functions 'Bases' calculates the global quantities: - Vector.basis tuple of basis vectors Vector.base_to_index dictionary to convert base to base inded Vector.metric metric tensor represented as a matrix of symbols and numbers """ Vector.is_orthogonal = False Vector.coords = coords Vector.subscripts = [] base_name_lst = base.split(' ') # Define basis vectors if '*' in base: base_lst = base.split('*') base = base_lst[0] Vector.subscripts = base_lst[1].split('|') base_name_lst = [] for subscript in Vector.subscripts: base_name_lst.append(base + '_' + subscript) else: if len(base_name_lst) > 1: Vector.subscripts = [] for base_name in base_name_lst: tmp = base_name.split('_') Vector.subscripts.append(tmp[-1]) elif len(base_name_lst) == 1 and Vector.coords is not None: base_name_lst = [] for coord in Vector.coords: Vector.subscripts.append(str(coord)) base_name_lst.append(base + '_' + str(coord)) else: raise TypeError("'%s' does not define basis vectors" % base) basis = [] base_to_index = {} index = 0 for base_name in base_name_lst: basis_vec = Vector(base_name) basis.append(basis_vec) base_to_index[basis_vec.obj] = index index += 1 Vector.base_to_index = base_to_index Vector.basis = tuple(basis) # define metric tensor default_metric = [] for bv1 in Vector.basis: row = [] for bv2 in Vector.basis: row.append(Vector.basic_dot(bv1, bv2)) default_metric.append(row) Vector.metric = Matrix(default_metric) if metric is not None: if metric[0] == '[' and metric[-1] == ']': Vector.is_orthogonal = True metric_str_lst = metric[1:-1].split(',') Vector.metric = [] for g_ii in metric_str_lst: Vector.metric.append(S(g_ii)) Vector.metric = Matrix(Vector.metric) else: metric_str_lst = flatten(str_array(metric)) for index in range(len(metric_str_lst)): if metric_str_lst[index] != '#': Vector.metric[index] = S(metric_str_lst[index]) Vector.metric_dict = {} # Used to calculate dot product N = range(len(Vector.basis)) if Vector.is_orthogonal: for ii in N: Vector.metric_dict[Vector.basis[ii].obj] = Vector.metric[ii] else: for irow in N: for icol in N: Vector.metric_dict[( Vector.basis[irow].obj, Vector.basis[icol].obj)] = Vector.metric[irow, icol] # calculate tangent vectors and metric for curvilinear basis if curv != (None, None): X = S.Zero for (coef, base) in zip(curv[0], Vector.basis): X += coef * base.obj Vector.tangents = [] for (coord, norm) in zip(Vector.coords, curv[1]): tau = diff(X, coord) tau = trigsimp(tau) tau /= norm tau = expand(tau) Vtau = Vector() Vtau.obj = tau Vector.tangents.append(Vtau) metric = [] for tv1 in Vector.tangents: row = [] for tv2 in Vector.tangents: row.append(tv1 * tv2) metric.append(row) metric = Matrix(metric) metric = metric.applyfunc(TrigSimp) Vector.metric_dict = {} if metric.is_diagonal: Vector.is_orthogonal = True tmp_metric = [] for ii in N: tmp_metric.append(metric[ii, ii]) Vector.metric_dict[Vector.basis[ii].obj] = metric[ii, ii] Vector.metric = Matrix(tmp_metric) else: Vector.is_orthogonal = False Vector.metric = metric for irow in N: for icol in N: Vector.metric_dict[( Vector.basis[irow].obj, Vector.basis[icol].obj)] = Vector.metric[irow, icol] Vector.norm = curv[1] if debug: oprint('Tangent Vectors', Vector.tangents, 'Metric', Vector.metric, 'Metric Dictionary', Vector.metric_dict, 'Normalization', Vector.norm, dict_mode=True) # calculate derivatives of tangent vectors Vector.dtau_dict = None dtau_dict = {} for x in Vector.coords: for (tau, base) in zip(Vector.tangents, Vector.basis): dtau = tau.diff(x).applyfunc(TrigSimp) result = S.Zero for (t, b) in zip(Vector.tangents, Vector.basis): t_dtau = TrigSimp(t * dtau) result += t_dtau * b.obj dtau_dict[(base.obj, x)] = result Vector.dtau_dict = dtau_dict if debug: oprint('Basis Derivatives', Vector.dtau_dict, dict_mode=True) return tuple(Vector.basis)