Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Copyright 2011-2013 Kwant authors. 

2# 

3# This file is part of Kwant. It is subject to the license terms in the file 

4# LICENSE.rst found in the top-level directory of this distribution and at 

5# https://kwant-project.org/license. A list of Kwant authors can be found in 

6# the file AUTHORS.rst at the top-level directory of this distribution and at 

7# https://kwant-project.org/authors. 

8 

9import numpy as np 

10 

11 

12def prepare_for_fortran(overwrite, *args): 

13 """Convert arrays to Fortran format. 

14 

15 This function takes a number of array objects in `args` and converts them 

16 to a format that can be directly passed to a Fortran function (Fortran 

17 contiguous NumPy array). If the arrays have different data type, they 

18 converted arrays are cast to a common compatible data type (one of NumPy's 

19 `float32`, `float64`, `complex64`, `complex128` data types). 

20 

21 If `overwrite` is ``False``, an NumPy array that would already be in the 

22 correct format (Fortran contiguous, right data type) is neverthelessed 

23 copied. (Hence, overwrite = True does not imply that acting on the 

24 converted array in the return values will overwrite the original array in 

25 all cases -- it does only so if the original array was already in the 

26 correct format. The conversions require copying. In fact, that's the same 

27 behavior as in SciPy, it's just not explicitly stated there) 

28 

29 If an argument is ``None``, it is just passed through and not used to 

30 determine the proper data type. 

31 

32 `prepare_for_lapack` returns a character indicating the proper 

33 data type in LAPACK style ('s', 'd', 'c', 'z') and a list of 

34 properly converted arrays. 

35 """ 

36 

37 # Make sure we have NumPy arrays 

38 mats = [None]*len(args) 

39 for i in range(len(args)): 

40 if args[i] is not None: 40 ↛ 48line 40 didn't jump to line 48, because the condition on line 40 was never false

41 arr = np.asanyarray(args[i]) 

42 if not np.issubdtype(arr.dtype, np.number): 42 ↛ 43line 42 didn't jump to line 43, because the condition on line 42 was never true

43 raise ValueError("Argument cannot be interpreted " 

44 "as a numeric array") 

45 

46 mats[i] = (arr, arr is not args[i] or overwrite) 

47 else: 

48 mats[i] = (None, True) 

49 

50 # First figure out common dtype 

51 # Note: The return type of common_type is guaranteed to be a floating point 

52 # kind. 

53 dtype = np.common_type(*[arr for arr, ovwrt in mats if arr is not None]) 

54 

55 if dtype == np.float32: 55 ↛ 56line 55 didn't jump to line 56, because the condition on line 55 was never true

56 lapacktype = 's' 

57 elif dtype == np.float64: 57 ↛ 58line 57 didn't jump to line 58, because the condition on line 57 was never true

58 lapacktype = 'd' 

59 elif dtype == np.complex64: 59 ↛ 60line 59 didn't jump to line 60, because the condition on line 59 was never true

60 lapacktype = 'c' 

61 elif dtype == np.complex128: 61 ↛ 64line 61 didn't jump to line 64, because the condition on line 61 was never false

62 lapacktype = 'z' 

63 else: 

64 raise AssertionError("Unexpected data type from common_type") 

65 

66 ret = [ lapacktype ] 

67 for npmat, ovwrt in mats: 

68 # Now make sure that the array is contiguous, and copy if necessary. 

69 if npmat is not None: 69 ↛ 89line 69 didn't jump to line 89, because the condition on line 69 was never false

70 if npmat.ndim == 2: 

71 if not npmat.flags["F_CONTIGUOUS"]: 

72 npmat = np.asfortranarray(npmat, dtype = dtype) 

73 elif npmat.dtype != dtype: 

74 npmat = npmat.astype(dtype) 

75 elif not ovwrt: 75 ↛ 89line 75 didn't jump to line 89, because the condition on line 75 was never false

76 # ugly here: copy makes always C-array, no way to tell it 

77 # to make a Fortran array. 

78 npmat = np.asfortranarray(npmat.copy()) 

79 elif npmat.ndim == 1: 79 ↛ 87line 79 didn't jump to line 87, because the condition on line 79 was never false

80 if not npmat.flags["C_CONTIGUOUS"]: 80 ↛ 81line 80 didn't jump to line 81, because the condition on line 80 was never true

81 npmat = np.ascontiguousarray(npmat, dtype = dtype) 

82 elif npmat.dtype != dtype: 

83 npmat = npmat.astype(dtype) 

84 elif not ovwrt: 

85 npmat = np.asfortranarray(npmat.copy()) 

86 else: 

87 raise ValueError("Dimensionality of array is not 1 or 2") 

88 

89 ret.append(npmat) 

90 

91 return tuple(ret) 

92 

93 

94def assert_fortran_mat(*mats): 

95 """Check if the input ndarrays are all proper Fortran matrices.""" 

96 

97 # This is a workaround for a bug in NumPy version < 2.0, 

98 # where 1x1 matrices do not have the F_Contiguous flag set correctly. 

99 for mat in mats: 

100 if (mat is not None and (mat.shape[0] > 1 or mat.shape[1] > 1) and 

101 not mat.flags["F_CONTIGUOUS"]): 

102 raise ValueError("Input matrix must be Fortran contiguous") 

103 

104 

105def assert_fortran_matvec(*arrays): 

106 """Check if the input ndarrays are all proper Fortran matrices 

107 or vectors.""" 

108 

109 # This is a workaround for a bug in NumPy version < 2.0, 

110 # where 1x1 matrices do not have the F_Contiguous flag set correctly. 

111 for arr in arrays: 

112 if not arr.ndim in (1, 2): 112 ↛ 113line 112 didn't jump to line 113, because the condition on line 112 was never true

113 raise ValueError("Input must be either a vector " 

114 "or a matrix.") 

115 

116 if (not arr.flags["F_CONTIGUOUS"] or 116 ↛ 118line 116 didn't jump to line 118, because the condition on line 116 was never true

117 (arr.ndim == 2 and arr.shape[0] == 1 and arr.shape[1] == 1) ): 

118 raise ValueError("Input must be a Fortran ordered " 

119 "NumPy array")