def test__newindex(self): # Following 3 lines are just to get the mappings st = SymbolicTensor('ABcDe', symbol='a', create_tensor=False) # one-based input index, voigt notation => (6, 5, 2, 2, 1) index = [[1, 2], [1, 3], [2], [2, 2], [1]] # Shift to make the index zero based index = [item - 1 for sublist in index for item in sublist] approx = st._newindex(index, start=1, voigt=True) exact = [6, 5, 2, 2, 1] assert_equal(approx, exact) # sort index 0 and 3 st = SymbolicTensor('ABcAe', symbol='a', create_tensor=False) approx = st._newindex(index, start=1, voigt=True) # Unsorted => exact = [6, 5, 2, 2, 1] # Sorted => swap indices 0 and 3 exact = [2, 5, 2, 6, 1] assert_equal(approx, exact) # Try setting `voigt=False`, (2, 6, 5) -> (2, 5, 6) -> (2, 1, 3, 1, 2) # Note that sorting with `voigt=False`gives the following ordering: # (1, 1), (2, 2), (3, 3), (1, 2), (1, 3), (2, 3) index = [[2], [1, 2], [1, 3]] index = [item - 1 for sublist in index for item in sublist] st = SymbolicTensor('aBC', symbol='a', create_tensor=False) approx = st._newindex(index, start=1, voigt=False) exact = [2, 1, 2, 1, 3] assert_equal(approx, exact)
def test__repeated_indices(self): name = 'ABcDefgABcDeABc' exact = [[0, 7, 12], [1, 8, 13], [2, 9, 14], [3, 10], [4, 11]] # Don't try creating a tensor with more than six indices, you'll # probably run out of memory. approx = SymbolicTensor._repeated_indices(name) approx.sort() assert_equal(approx, exact) name = ['i1', 'j2', 'i1', 'i1', 'j2', 'k1'] approx = SymbolicTensor._repeated_indices(name) approx.sort() exact = [[0, 2, 3], [1, 4]] assert_equal(approx, exact)
def sym_reduce(indices, symbol_name, sym_group): # Choose a symmetry group (e.g. '3m') sg = RedSgSymOps() symops = sg(sym_group) # Create a 5th-rank symbolic tensor with indices 1 and 3 interchangeable print(indices) print(symbol_name) st = SymbolicTensor(indices, symbol_name[0], start=1) # Solve for the unique tensor elements fullsol, polyring = st.sol_details(symops) print(fullsol)
def test__parse_name(self): name = 'a2,b2,c1,b2,a2,b1' approx_dims, approx_repeats = SymbolicTensor._parse_name(name) exact_dims = [2, 2, 1, 2, 2, 1] exact_repeats = [[0, 4], [1, 3]] assert_equal(approx_dims, exact_dims) approx_repeats.sort() assert_equal(approx_repeats, exact_repeats) name = 'ABcAe' exact_dims = [2, 2, 1, 2, 1] exact_repeats = [[0, 3]] approx_dims, approx_repeats = SymbolicTensor._parse_name(name) assert_equal(approx_dims, exact_dims) approx_repeats.sort() assert_equal(approx_repeats, exact_repeats)
def create_linear_system(symbol, superscript, sym_group='622', tdim=2): sg = RedSgSymOps() print(sg.symops['6parZ3']) symops = sg(sym_group) symop = symops[0] R = Matrix(symop) Rsym = Matrix([[Symbol('R_{{{},{}}}'.format(i, j)) for j in range(1, 4)] for i in range(1, 4)]) print('Rsym=\n', latex(Rsym)) print('R=\n', latex(R)) print(symop) ivm, vm = SymbolicTensor.voigt_map(2) print(ivm) print(vm) indices0 = list(product(range(3), repeat=tdim)) indices1 = list(product(range(1, 4), repeat=tdim)) print(indices0) print(indices1) lhs = Matrix([[Rsym[I, i] * Rsym[J, j] for (i, j) in indices0] for (I, J) in indices0]) print(latex(lhs)) vec = Matrix([[Symbol('c_{{{},{}}}'.format(i, j))] for (i, j) in indices1]) print(latex(vec)) vvec = Matrix([[Symbol('c_{{{}}}'.format(vm[k] + 1))] for k in indices0]) print(latex(vvec)) lines = [] frac_lines = [] redfrac_lines = [] symbol += '^{{{}}}'.format(superscript) for (I, J) in indices: line = '&'.join([ "{}_{{{}{}}} {}_{{{}{}}}".format(symbol, I, i, symbol, J, j) for (i, j) in indices ]) lines.append(line) Iint = int(I) - 1 Jint = int(J) - 1 frac_line = '&'.join([ "{} \cdot {}".format(symop[Iint, int(i) - 1], symop[Jint, int(j) - 1]) for (i, j) in indices ]) frac_line = frac_line.replace('sqrt(3)', '\\sqrt{3}') frac_lines.append(frac_line) redfrac_line = '&'.join([ "{}".format(4 * symop[Iint, int(i) - 1] * symop[Jint, int(j) - 1]) for (i, j) in indices ]) redfrac_line = redfrac_line.replace('sqrt(3)', '\\sqrt{3}') redfrac_lines.append(redfrac_line) print('\\\\'.join(lines)) print('\\\\'.join(frac_lines)) print('\\\\'.join(redfrac_lines))
def test_voigt_map(self): exact_vm = { (1, 1): 1, (2, 2): 2, (3, 3): 3, (2, 3): 4, (3, 2): 4, (1, 3): 5, (3, 1): 5, (1, 2): 6, (2, 1): 6 } exact_ivm = { 1: (1, 1), 2: (2, 2), 3: (3, 3), 4: (2, 3), 5: (1, 3), 6: (1, 2) } approx_ivm, approx_vm = SymbolicTensor.voigt_map(dim=2, start=1) assert_equal(approx_vm, exact_vm) assert_equal(approx_ivm, exact_ivm)
def compare_tables(indices_symbol, symbolnames, colnames, data): """ Parameters ---------- indices_symbol: string Tensor symbol, e.g. 'aB' for 2nd-order piezoelectric tensor indices: list or tuple of integers A list containing tuples with the same length as the number of indices of the tensor of interest. colnames : list of strings The column names of Chris Kube's tables data : 2d array of strings The columns of data corresponding to Chris Kube's tensor symmetries """ # Discrepancies # 6/mm should be 6/mmm # m\bar{3} should be \bar{3}m # m3m should be m\bar{3}m # 6m2 should be \bar{6}m2 # m3 should be m\bar{3} tex_map = {# triclinic '1': '1', '1d': r'$\bar{1}$', # monoclinic '2': '2', 'm': r'$m$', '2/m': r'$2/m$', # orthorhombic '222': '222', 'mm2': r'$mm2$', 'mmm': r'$mmm$', # tetragonal '4': '4', '4d': r'$\bar{4}$', '4/m': '$4/m$', '422': '422', '4mm': r'$4mm$', '4d2m': r'$\bar{4}2m$', '4/mmm': r'$4/mmm$', # cubic '23': '23', 'm3d': r'$m\bar{3}$', '432': '432', '4d3m': r'$\bar{4}3m$', 'm3dm': r'$m\bar{3}m$', # hexagonal '3': '3', '3d': r'$\bar{3}$', '32': '32', '3m': r'$3m$', '3dm': r'$\bar{3}m$', '6': '6', '6d': r'$\bar{6}$', '6/m': r'$6/m$', '622': '622', '6mm': r'$6mm$', '6dm2': r'$\bar{6}m2$', '6/mmm': r'$6/mmm$'} sg = SgSymOps() crystalclasses = sg.flat_ieee.keys() # sg = RedSgSymOps() # crystalclasses = sg.group.keys() # Debug misspellings in Kube tables # print('number of crystalclasses = {}'.format(len(crystalclasses))) # for crystalclass in crystalclasses: # kube_key = tex_map[crystalclass] # if kube_key in colnames: # colnames.remove(kube_key) # else: # print(kube_key) # print(colnames) local_dict = dict((name, Symbol(name)) for name in symbolnames) first_letter = symbolnames[0][0] differences = False # Used for checking if the input file has the correct names # for crystalclass in crystalclasses: # print(colnames.index(tex_map[crystalclass])) for crystalclass in crystalclasses: # if crystalclass != '6': # continue print('Crystal class {}'.format(crystalclass)) logging.info('Crystal class {}'.format(crystalclass)) symops = sg(crystalclass) st = SymbolicTensor(indices_symbol, first_letter) fullsol, R = st.sol_details(symops) # print(fullsol) inputcol = data[:, colnames.index(tex_map[crystalclass])] for inputval, symbolname in zip(inputcol, symbolnames): val = fullsol[symbolname] parsedval = parse_expr(inputval, local_dict) if R(val) != R(parsedval): differences = True print('{}: val = {}, inputval = {}'.format(symbolname, val, inputval)) logging.info('{}: val = {}, inputval = {}'.format(symbolname, val, inputval)) print('Differences = {}'.format(differences)) logging.info('Differences = {}'.format(differences))
def test__create_slices(self): dims = [2, 1, 1, 3] exact = [slice(0, 2), slice(2, 3), slice(3, 4), slice(4, 7)] approx = SymbolicTensor._create_slices(dims) assert_equal(approx, exact)