Skip to content

Commit

Permalink
Merge pull request #55 from DLR-AE/feature_python3.12
Browse files Browse the repository at this point in the history
Add Python 3.12 to testing
  • Loading branch information
ArneVoss authored Jan 8, 2025
2 parents cf8b8bc + cd2d959 commit 452e5ec
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 45 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
matrix:
# Add multiple Python versions here to run tests on new(er) versions.
python-version: ["3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]
fail-fast: false
steps:
- uses: actions/checkout@v3
Expand All @@ -42,7 +42,7 @@ jobs:
strategy:
matrix:
# Add multiple Python versions here to run tests on new(er) versions.
python-version: ["3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]
fail-fast: false
# Step 1 to make GUIs work, see https://pytest-qt.readthedocs.io/en/latest/troubleshooting.html
env:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/coding-style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
# Add the Python versions here to run tests on new(er) versions.
python-version: ["3.11"]
python-version: ["3.12"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -41,7 +41,7 @@ jobs:
strategy:
matrix:
# Add multiple Python versions here to run tests on new(er) versions.
python-version: ["3.11"]
python-version: ["3.12"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/regression-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
matrix:
# Add multiple Python versions here to run tests on new(er) versions.
python-version: ["3.11"]
python-version: ["3.12"]
# Step 1 to make GUIs work, see https://pytest-qt.readthedocs.io/en/latest/troubleshooting.html
env:
DISPLAY: ':99.0'
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
strategy:
matrix:
# Select Python version to be used for compiling here.
python-version: ["3.11"]
python-version: ["3.12"]
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
Expand Down
4 changes: 2 additions & 2 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ stages:

.virtenv: &virtualenv
- source /work/f_jwsb/software/miniforge3/etc/profile.d/conda.sh
# This is the environment where I installed all dependencies via 'conda install loadskernel-extras'.
- conda activate my_env
# This is the environment where I installed all dependencies.
- conda activate lk_ci_python3.12
# To make things faster, re-use existing site packages.
- python -m venv virtualenv --system-site-packages
- source virtualenv/bin/activate
Expand Down
10 changes: 5 additions & 5 deletions loadskernel/equations/frequency_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ def calc_psd_vonKarman(self, freqs):
if freqs[0] == 0.0:
psd_karman[0] = 0.0
# Calculate the RMS value for cross-checking. Exclude first frequency with f=0.0 from the integral.
logging.info('RMS of PSD input (should approach 1.0): {:.4f}'.format(np.trapz(psd_karman[1:], freqs[1:]) ** 0.5))
logging.info('RMS of PSD input (should approach 1.0): {:.4f}'.format(np.trapezoid(psd_karman[1:], freqs[1:]) ** 0.5))
return psd_karman

def calc_gust_excitation(self, freqs, t):
Expand Down Expand Up @@ -266,8 +266,8 @@ def calc_gust_excitation(self, freqs, t):
plt.grid(True)
plt.show()
print('RMS of PSD input (must be close to u_sigma): {:.4f}'.format(np.trapz(psd_karman, freqs)**0.5))
print('RMS in freq. dom: {:.4f}'.format(np.trapz(psd_scaled, freqs)**0.5))
print('RMS of PSD input (must be close to u_sigma): {:.4f}'.format(np.trapezoid(psd_karman, freqs)**0.5))
print('RMS in freq. dom: {:.4f}'.format(np.trapezoid(psd_scaled, freqs)**0.5))
w_turb_f = psd_scaled*np.exp(1j*random_phases)
print('The amplitude may not change after adding a random phase: {}'.format(np.allclose(np.abs(w_turb_f), psd_scaled)))
Expand Down Expand Up @@ -337,7 +337,7 @@ def eval_equations(self):
# Force Summation Method: P = Pext + Piner
H = Haero + Hgust + Hiner

A = np.trapz(np.real(H * H.conj()) * psd_karman, self.positiv_fftfreqs) ** 0.5
A = np.trapezoid(np.real(H * H.conj()) * psd_karman, self.positiv_fftfreqs) ** 0.5
Pmon = self.u_sigma * A

logging.info('calculating correlations')
Expand All @@ -346,7 +346,7 @@ def eval_equations(self):
# Once the integral is done, the matrix is much smaller.
correlations = np.zeros((self.mongrid['n'] * 6, self.mongrid['n'] * 6))
for i_row in range(6 * self.mongrid['n']):
correlations[i_row, :] = np.trapz(np.real(H[i_row, :].conj() * H) * psd_karman, self.positiv_fftfreqs)
correlations[i_row, :] = np.trapezoid(np.real(H[i_row, :].conj() * H) * psd_karman, self.positiv_fftfreqs)
correlations /= (A * A[:, None])

response = {'Pmon_turb': np.expand_dims(Pmon, axis=0),
Expand Down
2 changes: 1 addition & 1 deletion loadskernel/plotting_standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def create_axes(self, logo=True):

def plot_monstations(self, filename_pdf):
# launch plotting
self.pp = PdfPages(filename_pdf, keep_empty=False)
self.pp = PdfPages(filename_pdf)
self.potato_plots()
if self.cuttingforces_wing:
self.cuttingforces_along_axis_plots(monstations=self.cuttingforces_wing, axis=1)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def my_setup():
python_requires='>=3.10',
install_requires=['PanelAero',
'matplotlib',
'numpy==1.26.*', # changes in numpy > 2.0 need to be investigated / reviewed first
'numpy',
'scipy',
'psutil',
'h5py',
Expand Down
6 changes: 3 additions & 3 deletions tests/helper_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,20 @@ def compare_hdf5_datasets(self, item_a, item_b, key):
return self.compare_items(item_a[()], item_b, key)

def compare_items(self, item_a, item_b, key):
# Check if the item shall be handled in a special way
# Check if the item shall be handled in a special way.
if key in self.list_ignore_sign:
# Compare the absolute values.
item_a = np.abs(item_a)
item_b = np.abs(item_b)
elif key in self.list_sum:
if key in self.list_sum:
# Calculate the sum along the last axis.
item_a = np.sum(item_a, axis=-1)
item_b = np.sum(item_b, axis=-1)

if issparse(item_a):
# sparse efficiency, compare != instead of ==
result = np.all(np.invert((item_a != item_b).toarray()))
elif isinstance(item_a, np.ndarray):
elif isinstance(item_a, (np.ndarray, float)):
if item_a.dtype == 'object':
# numpy objects can be compare with np.equal
result = np.all(np.equal(item_a, item_b))
Expand Down
74 changes: 47 additions & 27 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def get_test_dir(tmpdir_factory):
return str(test_dir)


class TestDiscus2c(HelperFunctions):
class PreMainPostFunctional(HelperFunctions):
job_name = 'jcl_Discus2c'
path_input = os.path.join(path_examples, 'Discus2c', 'JCLs')

Expand All @@ -53,6 +53,11 @@ def test_postprocessing_functional(self, get_test_dir):
path_output=get_test_dir)
k.run()


class TestDiscus2c(PreMainPostFunctional):
job_name = 'jcl_Discus2c'
path_input = os.path.join(path_examples, 'Discus2c', 'JCLs')

def test_preprocessing_results(self, get_test_dir):
# do comparisons
logging.info('Comparing model with reference')
Expand Down Expand Up @@ -167,30 +172,50 @@ class TestAllegraFreqdom(TestDiscus2c):
path_input = os.path.join(path_examples, 'Allegra', 'JCLs')


class TestAllegraFlutter(HelperFunctions):
class TestAllegraFlutter(PreMainPostFunctional):
job_name = 'jcl_ALLEGRA_flutter'
path_input = os.path.join(path_examples, 'Allegra', 'JCLs')

def test_preprocessing_functional(self, get_test_dir):
# Here you launch the Loads Kernel with your job
k = program_flow.Kernel(self.job_name, pre=True, main=False, post=False,
path_input=self.path_input,
path_output=get_test_dir)
k.run()
def test_preprocessing_results(self, get_test_dir):
# do comparisons
logging.info('Comparing model with reference')
model = io_functions.data_handling.load_hdf5(get_test_dir + 'model_' + self.job_name + '.hdf5')
reference_model = io_functions.data_handling.load_hdf5(path_reference + 'model_' + self.job_name + '.hdf5')
assert self.compare_dictionaries(model, reference_model), "model does NOT match reference"

def test_mainprocessing_functional(self, get_test_dir):
# Here you launch the Loads Kernel with your job
k = program_flow.Kernel(self.job_name, pre=False, main=True, post=False,
path_input=self.path_input,
path_output=get_test_dir)
k.run()
def test_mainprocessing_results(self, get_test_dir):
logging.info('Comparing response with reference')
responses = io_functions.data_handling.load_hdf5_responses(self.job_name, get_test_dir)
reference_responses = io_functions.data_handling.load_hdf5_responses(self.job_name, path_reference)

def test_postprocessing_functional(self, get_test_dir):
# Here you launch the Loads Kernel with your job
k = program_flow.Kernel(self.job_name, pre=False, main=False, post=True,
path_input=self.path_input,
path_output=get_test_dir)
k.run()
# Responses 0 and 1: For the K and KE method, Vtas, damping and frequencies are quantities of interest.
for resp_a, resp_b in zip(responses[:2], reference_responses[:2]):
# Only compare results in an area where the results are meaningful.
pos_a = (resp_a['Vtas'][()] > 350.0) & (resp_a['Vtas'][()] < 450.0)
pos_b = (resp_b['Vtas'][()] > 350.0) & (resp_b['Vtas'][()] < 450.0)
assert self.compare_items(resp_a['Vtas'][pos_a],
resp_b['Vtas'][pos_b], 'Vtas'), "Vtas does NOT match reference"
assert self.compare_items(resp_a['damping'][pos_a],
resp_b['damping'][pos_b], 'damping'), "damping does NOT match reference"
assert self.compare_items(resp_a['freqs'][pos_a],
resp_b['freqs'][pos_b], 'freqs'), "freqs do NOT match reference"

# Responses 2 and 3: For the PK methods, eigenvalues, damping and freqs are quantities of interest.
for resp_a, resp_b in zip(responses[2:], reference_responses[2:]):
# Only compare results in an area where the results are meaningful.
pos_a = (resp_a['Vtas'][()] > 350.0) & (resp_a['Vtas'][()] < 450.0)
pos_b = (resp_b['Vtas'][()] > 350.0) & (resp_b['Vtas'][()] < 450.0)
assert self.compare_items(resp_a['eigenvalues'][pos_a],
resp_b['eigenvalues'][pos_b], 'eigenvalues'), "eigenvalues do NOT match reference"
assert self.compare_items(resp_a['damping'][pos_a],
resp_b['damping'][pos_b], 'damping'), "damping does NOT match reference"
assert self.compare_items(resp_a['freqs'][pos_a],
resp_b['freqs'][pos_b], 'freqs'), "freqs do NOT match reference"


class TestAllegraLimitTurbulence(PreMainPostFunctional):
job_name = 'jcl_ALLEGRA_limitturbulence'
path_input = os.path.join(path_examples, 'Allegra', 'JCLs')

def test_preprocessing_results(self, get_test_dir):
# do comparisons
Expand All @@ -207,21 +232,16 @@ def test_mainprocessing_results(self, get_test_dir):
assert self.compare_lists(responses, reference_responses), "response does NOT match reference"


class TestAllegraLimitTurbulence(TestAllegraFlutter):
job_name = 'jcl_ALLEGRA_limitturbulence'
path_input = os.path.join(path_examples, 'Allegra', 'JCLs')


class TestHAPO6Trim(TestDiscus2c):
job_name = 'jcl_HAP-O6'
path_input = os.path.join(path_examples, 'HAP-O6', 'JCLs')


class TestHAPO6Derivatives(TestAllegraFlutter):
class TestHAPO6Derivatives(TestAllegraLimitTurbulence):
job_name = 'jcl_HAP-O6_derivatives'
path_input = os.path.join(path_examples, 'HAP-O6', 'JCLs')


class TestHAPO6StateSpaceSystem(TestAllegraFlutter):
class TestHAPO6StateSpaceSystem(TestAllegraLimitTurbulence):
job_name = 'jcl_HAP-O6_sss'
path_input = os.path.join(path_examples, 'HAP-O6', 'JCLs')

0 comments on commit 452e5ec

Please sign in to comment.