pyvpmr 241217__cp38-cp38-musllinux_1_2_x86_64.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.
- _pyvpmr.cpython-38-x86_64-linux-gnu.so +0 -0
- pyvpmr/__init__.py +148 -0
- pyvpmr-241217.dist-info/LICENSE +674 -0
- pyvpmr-241217.dist-info/METADATA +989 -0
- pyvpmr-241217.dist-info/RECORD +12 -0
- pyvpmr-241217.dist-info/WHEEL +5 -0
- pyvpmr-241217.dist-info/top_level.txt +2 -0
- pyvpmr.libs/libgcc_s-a0b57c20.so.1 +0 -0
- pyvpmr.libs/libgmp-e9987f27.so.10.5.0 +0 -0
- pyvpmr.libs/libmpfr-2b6b67fa.so.6.2.1 +0 -0
- pyvpmr.libs/libstdc++-0d31ccbe.so.6.0.32 +0 -0
- pyvpmr.libs/libtbb-128a143d.so.12.12 +0 -0
Binary file
|
pyvpmr/__init__.py
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
# Copyright (C) 2024 Theodore Chang
|
2
|
+
#
|
3
|
+
# This program is free software: you can redistribute it and/or modify
|
4
|
+
# it under the terms of the GNU General Public License as published by
|
5
|
+
# the Free Software Foundation, either version 3 of the License, or
|
6
|
+
# (at your option) any later version.
|
7
|
+
#
|
8
|
+
# This program is distributed in the hope that it will be useful,
|
9
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
10
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
11
|
+
# GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License
|
14
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
15
|
+
|
16
|
+
from __future__ import annotations
|
17
|
+
|
18
|
+
import re
|
19
|
+
from typing import Callable
|
20
|
+
|
21
|
+
import numpy as np
|
22
|
+
from _pyvpmr import vpmr as vpmr_impl
|
23
|
+
from matplotlib import pyplot as plt
|
24
|
+
|
25
|
+
vpmr = vpmr_impl
|
26
|
+
|
27
|
+
|
28
|
+
def split(result: str) -> tuple | None:
|
29
|
+
"""
|
30
|
+
Split the output of the vpmr program into two arrays of complex numbers.
|
31
|
+
|
32
|
+
:param result: The raw output of the vpmr program.
|
33
|
+
:return: A tuple of two arrays of complex numbers.
|
34
|
+
"""
|
35
|
+
split_r = result.strip().split('\n')
|
36
|
+
regex = re.compile(r'([+\-]\d+\.\d+e[+\-]\d+){2}j')
|
37
|
+
items = [i for i in split_r if regex.match(i)]
|
38
|
+
if len(items) % 2 != 0:
|
39
|
+
print('something wrong with the output')
|
40
|
+
return None
|
41
|
+
|
42
|
+
m_complex = [complex(i) for i in items[:len(items) // 2]]
|
43
|
+
s_complex = [complex(i) for i in items[len(items) // 2:]]
|
44
|
+
return np.array(m_complex), np.array(s_complex)
|
45
|
+
|
46
|
+
|
47
|
+
def plot(
|
48
|
+
m: list | np.ndarray, s: list | np.ndarray, kernel: Callable, *,
|
49
|
+
size: tuple[float, float] = (6, 4),
|
50
|
+
xlim: tuple[float, float] = (0, 10),
|
51
|
+
show: bool = True,
|
52
|
+
save_to: str = None
|
53
|
+
):
|
54
|
+
"""
|
55
|
+
Plot the kernel function and the approximation.
|
56
|
+
|
57
|
+
:param m: The list of m values.
|
58
|
+
:param s: The list of s values.
|
59
|
+
:param kernel: The kernel function.
|
60
|
+
:param size: The size of the figure.
|
61
|
+
:param xlim: The x-axis limits.
|
62
|
+
:param show: If to show the figure.
|
63
|
+
:param save_to: Where to save the figure.
|
64
|
+
"""
|
65
|
+
x = np.linspace(*xlim, 401)
|
66
|
+
|
67
|
+
y_ref = np.zeros(len(x))
|
68
|
+
for i in range(len(x)):
|
69
|
+
y_ref[i] = kernel(x[i])
|
70
|
+
|
71
|
+
y = np.zeros(len(x), dtype=complex)
|
72
|
+
for ml, sl in zip(m, s):
|
73
|
+
y += ml * np.exp(-sl * x)
|
74
|
+
|
75
|
+
fig = plt.figure(figsize=size)
|
76
|
+
|
77
|
+
ax1 = plt.gca()
|
78
|
+
ax1.plot(x, y_ref, 'b-', label='kernel', linewidth=2)
|
79
|
+
ax1.plot(x, y.real, 'r', linestyle='dashdot', label='approximation', linewidth=3)
|
80
|
+
ax1.set_xlabel('time $t$ [s]')
|
81
|
+
ax1.set_ylabel('kernel function $g(t)$')
|
82
|
+
ax1.legend(loc='upper right', handlelength=4)
|
83
|
+
|
84
|
+
ax2 = plt.twinx()
|
85
|
+
ax2.plot(x, np.abs(y_ref - y), 'g--', label='absolute error', linewidth=1)
|
86
|
+
ax2.set_yscale('log')
|
87
|
+
ax2.set_ylabel('absolute error')
|
88
|
+
ax2.legend(loc='center right')
|
89
|
+
|
90
|
+
plt.xlim(np.min(x), np.max(x))
|
91
|
+
plt.tight_layout(pad=.05)
|
92
|
+
if show:
|
93
|
+
plt.show()
|
94
|
+
if save_to:
|
95
|
+
fig.savefig(save_to)
|
96
|
+
|
97
|
+
|
98
|
+
def _process_args(*args):
|
99
|
+
if len(args) == 1:
|
100
|
+
assert 2 == len(args[0])
|
101
|
+
m, s = args[0]
|
102
|
+
elif len(args) == 2:
|
103
|
+
m, s = args
|
104
|
+
else:
|
105
|
+
raise ValueError('Wrong number of arguments.')
|
106
|
+
|
107
|
+
if len(m) == len(s):
|
108
|
+
return np.array(m), np.array(s)
|
109
|
+
|
110
|
+
raise ValueError('The length of m and s must be the same.')
|
111
|
+
|
112
|
+
|
113
|
+
def to_global_damping(*args):
|
114
|
+
"""
|
115
|
+
Generate a command to use the kernel as a global nonviscous damping model in suanPan.
|
116
|
+
:param args: The m and s values.
|
117
|
+
:return: The command.
|
118
|
+
"""
|
119
|
+
command = '# The following can be used as a global nonviscous damping with the Newmark time integration.\n'
|
120
|
+
command += '# You may need to modify the first line to change tag and integration parameters.\n'
|
121
|
+
command += 'integrator NonviscousNewmark 1 .25 .5'
|
122
|
+
|
123
|
+
for m, s in zip(*_process_args(*args)):
|
124
|
+
command += f' \\\n{m.real:+.15e} {m.imag:+.15e} {s.real:+.15e} {s.imag:+.15e}'
|
125
|
+
|
126
|
+
command += '\n'
|
127
|
+
|
128
|
+
return command
|
129
|
+
|
130
|
+
|
131
|
+
def to_elemental_damping(*args):
|
132
|
+
"""
|
133
|
+
Generate a command to use the kernel as a per-element nonviscous damping model in suanPan.
|
134
|
+
:param args: The m and s values.
|
135
|
+
:return: The command.
|
136
|
+
"""
|
137
|
+
command = '# The following can be used as a per-element based nonviscous damping.\n'
|
138
|
+
command += '# You may need to modify the first line to change tags.\n'
|
139
|
+
command += '# Use the alternative form to apply to multiplier elements.\n'
|
140
|
+
command += '# modifier ElementalNonviscousGroup {unique_modifier_tag} {associated_element_group_tag}'
|
141
|
+
command += 'modifier ElementalNonviscous {unique_modifier_tag} {associated_element_tag}'
|
142
|
+
|
143
|
+
for m, s in zip(*_process_args(*args)):
|
144
|
+
command += f' \\\n{m.real:+.15e} {m.imag:+.15e} {s.real:+.15e} {s.imag:+.15e}'
|
145
|
+
|
146
|
+
command += '\n'
|
147
|
+
|
148
|
+
return command
|