tiwave 0.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
tiwave/__init__.py ADDED
File without changes
tiwave/constants.py ADDED
@@ -0,0 +1,22 @@
1
+ """
2
+ Useful constants, copied from lalsuite
3
+ """
4
+
5
+ # Nominal solar mass, kg
6
+ # MSUN_SI = GMSUN_SI / G_SI
7
+ MSUN_SI = 1.988409870698050731911960804878414216e30
8
+
9
+ # Geometrized nominal solar mass, m
10
+ # MRSUN_SI = GMSUN_SI / (C_SI * C_SI)
11
+ MRSUN_SI = 1.476625038050124729627979840144936351e3
12
+
13
+ # Geometrized nominal solar mass, s
14
+ # MTSUN_SI = GMSUN_SI / (C_SI * C_SI * C_SI)
15
+ MTSUN_SI = 4.925490947641266978197229498498379006e-6
16
+
17
+ # Parsec, m
18
+ PC_SI = 3.085677581491367e16
19
+
20
+ # Math constants
21
+ PI = 3.141592653589793
22
+ EULER_GAMMA = 0.5772156649015329
tiwave/utils.py ADDED
@@ -0,0 +1,164 @@
1
+ import copy
2
+
3
+ import taichi as ti
4
+ import taichi.math as tm
5
+ import numpy as np
6
+ from numpy.typing import NDArray
7
+
8
+ from .constants import *
9
+
10
+
11
+ ti_complex = ti.types.vector(2, float)
12
+
13
+
14
+ def sub_struct_from(parent):
15
+ """
16
+ Since inheritance is not supported in ti.dataclass currently, we use this func as
17
+ a decorator to copy members and bind methods of existing dataclass to current dataclass.
18
+ Only supporting inheritance of just one generation.
19
+ TODO:
20
+ - a usage example
21
+ - staticmethod
22
+ """
23
+ # parent_members = copy.deepcopy(parent.members)
24
+ # parent_methods = copy.deepcopy(parent.methods)
25
+ # values of the dict point to address of taichi type object or func, using shallow copy is fine
26
+ parent_members = copy.copy(parent.members)
27
+ parent_methods = copy.copy(parent.methods)
28
+
29
+ def sub_struct(cls):
30
+ [parent_members.pop(key) for key in getattr(cls, "removed_members", [])]
31
+ fields = parent_members
32
+ fields.update(getattr(cls, "__annotations__", {}))
33
+
34
+ substruct_methods = {
35
+ attr: getattr(cls, attr)
36
+ for attr in dir(cls)
37
+ if callable(getattr(cls, attr)) and not attr.startswith("__")
38
+ }
39
+ conflict_methods = [k for k in substruct_methods if k in parent_methods]
40
+ # TODO: can have problem if the parent of parent has already had the method with same name
41
+ for k in conflict_methods:
42
+ parent_methods[f"_parent_{k}"] = parent_methods[k]
43
+ parent_methods.update(substruct_methods)
44
+ fields["__struct_methods"] = parent_methods
45
+
46
+ return ti.types.struct(**fields)
47
+
48
+ return sub_struct
49
+
50
+
51
+ # def complex_ti_field_to_np_array(
52
+ # input_field: ti.MatrixField,
53
+ # ) -> NDArray:
54
+ # np_array = input_field.to_numpy()
55
+ # return np_array[:, 0] + 1j * np_array[:, 1]
56
+
57
+
58
+ # def complex_np_array_to_ti_field(
59
+ # input_array: NDArray, field_container: ti.MatrixField
60
+ # ) -> None:
61
+ # field_container.from_numpy(np.vstack([input_array.real, input_array.imag]).T)
62
+ # return None
63
+
64
+
65
+ @ti.dataclass
66
+ class UsefulPowers:
67
+ third: float
68
+ two_thirds: float
69
+ one: float
70
+ four_thirds: float
71
+ five_thirds: float
72
+ two: float
73
+ seven_thirds: float
74
+ eight_thirds: float
75
+ three: float
76
+ four: float
77
+ fourth: float
78
+ three_fourths: float
79
+ seven_sixths: float
80
+ log: float
81
+
82
+ @ti.pyfunc
83
+ def update(self, number: float):
84
+ self.third = number ** (1 / 3)
85
+ self.two_thirds = self.third * self.third
86
+ self.one = number
87
+ self.four_thirds = number * self.third
88
+ self.five_thirds = number * self.two_thirds
89
+ self.two = number * number
90
+ self.seven_thirds = self.two * self.third
91
+ self.eight_thirds = self.two * self.two_thirds
92
+ self.three = self.two * number
93
+ self.four = self.three * number
94
+ self.fourth = number ** (1 / 4)
95
+ self.three_fourths = self.fourth**3
96
+ self.seven_sixths = ti.sqrt(self.seven_thirds)
97
+ self.log = ti.log(number)
98
+
99
+
100
+ @ti.func
101
+ def gauss_elimination(Ab: ti.template()) -> ti.template():
102
+ """
103
+ Solving a system of linear equations Ax=b using Gauss elimination. Note the loop
104
+ unrolling is used here, do not use this function to solve systems with large dimension.
105
+
106
+ Parameters
107
+ ==========
108
+ Ab:
109
+ The matrix containing the coefficinet matrix and numbers for the right hand side,
110
+ having the dimension of (n, n+1).
111
+
112
+ Returns
113
+ =======
114
+ x:
115
+ The solution of the system.
116
+ """
117
+ for i in ti.static(range(Ab.n)):
118
+ for j in ti.static(range(i + 1, Ab.n)):
119
+ scale = Ab[j, i] / Ab[i, i]
120
+ Ab[j, i] = 0.0
121
+ for k in ti.static(range(i + 1, Ab.m)):
122
+ Ab[j, k] -= Ab[i, k] * scale
123
+ # Back substitution
124
+ x = ti.Vector.zero(float, Ab.n)
125
+ for i in ti.static(range(Ab.n - 1, -1, -1)):
126
+ x[i] = Ab[i, Ab.m - 1]
127
+ for k in ti.static(range(i + 1, Ab.n)):
128
+ x[i] -= Ab[i, k] * x[k]
129
+ x[i] = x[i] / Ab[i, i]
130
+ return x
131
+
132
+
133
+ # def initialize_waveform_container_from_frequencies_array(
134
+ # frequencies, return_form="polarization", include_tf=True
135
+ # ):
136
+ # """
137
+ # Parparing waveform_container of ti.field from frequencies of np.array
138
+
139
+ # Parameters:
140
+ # ===========
141
+ # frequencies: np.array
142
+
143
+ # Returns:
144
+ # ========
145
+ # frequency_field: ti.field
146
+ # waveform_container: ti.Struct.field({'plus': ti_complex, 'cross': ti_complex, 'tf': float})
147
+ # """
148
+ # ret_content = {}
149
+ # if return_form == "polarizations":
150
+ # ret_content.update({"plus": ti_complex, "cross": ti_complex})
151
+ # elif return_form == "amplitude_phase":
152
+ # ret_content.update({"amplitude": float, "phase": float})
153
+ # if include_tf:
154
+ # ret_content.update({"tf": float})
155
+ # waveform_field = ti.Struct.field(ret_content)
156
+
157
+ # data_length = len(frequencies)
158
+ # ti.root.dense(ti.i, data_length).place(waveform_field)
159
+ # waveform_container = waveform_field
160
+
161
+ # frequency_field = ti.field(dtype=float, shape=(data_length,))
162
+ # frequency_field.from_numpy(frequencies)
163
+
164
+ # return frequency_field, waveform_container