Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RomApp] Adding a database with SQLite #12313

Merged
merged 76 commits into from
Jun 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
2df1d40
Working version 1: FOM simualtions
Rbravo555 Apr 4, 2024
cf63b52
better description of names
Rbravo555 Apr 9, 2024
4c8c7b3
better description. Should we move to another class?
Rbravo555 Apr 9, 2024
5121632
data base for basis as well as FOM solutions
Rbravo555 Apr 9, 2024
c645a0e
update default name
Rbravo555 Apr 9, 2024
569dfd9
ROM and HROM working with database
Rbravo555 Apr 9, 2024
a0f3c27
minor improvement
Rbravo555 Apr 10, 2024
1c5d77c
error measurement working
Rbravo555 Apr 10, 2024
9ea805d
working with ResidualsProjected
Rbravo555 Apr 11, 2024
fbf6278
Moving database stuff to data_base.py
Rbravo555 Apr 11, 2024
2e87d43
clean
Rbravo555 Apr 11, 2024
551a922
home changes
Rbravo555 Apr 11, 2024
48d7bba
working for FOM, ROM, HROM, ResidualsProjected, Elements and Weights
Rbravo555 Apr 11, 2024
79ffdf2
Making sure right basis is loaded
Rbravo555 Apr 12, 2024
50d3b8d
Fix bug. Merge #12271 before continuing
Rbravo555 Apr 12, 2024
5e16267
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 Apr 17, 2024
661ff3b
add missing step in PG
Rbravo555 Apr 17, 2024
c3fd983
correctly placing error calculation for all projection strategies
Rbravo555 Apr 17, 2024
14acce7
working for all but PetrovGalerkin
Rbravo555 Apr 17, 2024
acba938
fully working, also PetrovGalerkin
Rbravo555 Apr 18, 2024
7718e86
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 Apr 23, 2024
0c4e5ef
improve summary generation
Rbravo555 Apr 23, 2024
552cee2
clean
Rbravo555 Apr 23, 2024
6da223c
fixed paths
Rbravo555 Apr 24, 2024
cc3d8e9
merge redundant methods
Rbravo555 Apr 24, 2024
0b9b345
clean
Rbravo555 Apr 24, 2024
4f291a7
much cleaner version
Rbravo555 Apr 25, 2024
8647a42
Clean
Rbravo555 Apr 25, 2024
acd253f
small bug fixed in PetrovGalerkin
Rbravo555 Apr 25, 2024
a0343ae
error handling
Rbravo555 Apr 25, 2024
2d5492a
adding Test stages to database
Rbravo555 Apr 25, 2024
15315f0
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 Apr 25, 2024
3d1b946
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 May 2, 2024
5357ad5
small issue merging master
Rbravo555 May 2, 2024
f99e4ac
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 May 7, 2024
a36dfb0
Adapting database to ANN-Enhanced PROM
Rbravo555 May 8, 2024
823f1d5
adapted data_base to ann_enhanced prom
Rbravo555 May 9, 2024
820c9e9
Improve database for multiple runs of neural network
Rbravo555 May 9, 2024
fae8256
Fixed bug
Rbravo555 May 9, 2024
33b068b
Adding test
Rbravo555 May 9, 2024
d51ad32
adding skip if not pandas
Rbravo555 May 10, 2024
f355bf7
erase leftover rom database in test rom manager
Rbravo555 May 10, 2024
48f3fea
erase rom_database in structural tests
Rbravo555 May 10, 2024
f71cc15
erase leftover database from thermal test
Rbravo555 May 10, 2024
de28b69
correctly testing within working folder
Rbravo555 May 10, 2024
9675413
handling empty mu_train and mu_test.
Rbravo555 May 10, 2024
370ae44
Making all methods public for better flexibility of RomManager
Rbravo555 May 10, 2024
c2e36e8
updating test for ann anhanced with databaase
Rbravo555 May 10, 2024
dba7209
Update applications/RomApplication/python_scripts/rom_nn_trainer.py
Rbravo555 May 14, 2024
8de595d
Update applications/RomApplication/python_scripts/rom_nn_trainer.py
Rbravo555 May 14, 2024
896158e
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 May 14, 2024
a4bb20d
solutions not separated into Test and Train, only FOM, ROM, HROM
Rbravo555 May 15, 2024
45acccf
Keeping previous behaviour for storing vkt and gid
Rbravo555 May 15, 2024
a4140c4
explicitly state name in gid and vtk in RomManager
Rbravo555 May 15, 2024
19cc450
erased redundant line
Rbravo555 May 15, 2024
e0e4cf7
changing fetching method from name to hash
Rbravo555 May 15, 2024
e04f815
Adding warning if not all snapshots available
Rbravo555 May 15, 2024
183f147
Storing QoI's in database
Rbravo555 May 28, 2024
9d58384
Storing nonconverged solutions in database
Rbravo555 May 28, 2024
7ed0e94
clean
Rbravo555 May 28, 2024
2c1dd56
adding flag to store nonconverged solutions
Rbravo555 May 28, 2024
eafc920
Merge branch 'master' into RomApp_RomDataBaseWithSQLite
Rbravo555 May 28, 2024
b5a4300
Adding new tables to Database test
Rbravo555 May 28, 2024
970ccce
making sure test empty folder exists
Rbravo555 May 29, 2024
690fce2
Updating parameters from nonconverged sols and NN
Rbravo555 Jun 21, 2024
2b9f1d7
Fixing small bugs
Rbravo555 Jun 24, 2024
600ed45
review comments on fstrings and tokens
Rbravo555 Jun 24, 2024
3bb9a02
change method name for better consistency
Rbravo555 Jun 24, 2024
eef1fd6
regular prints
Rbravo555 Jun 24, 2024
b22967a
correct import order
Rbravo555 Jun 24, 2024
6e896ce
clean
Rbravo555 Jun 24, 2024
36d2ceb
making sure to gather nonconverged sols if not in the database
Rbravo555 Jun 24, 2024
a2a3404
adding documentation to database class
Rbravo555 Jun 24, 2024
fea57c2
Fixing incompatibility in NN training
Rbravo555 Jun 25, 2024
393bedb
Format change in Error handling
Rbravo555 Jun 25, 2024
273cba3
using context manager in rom database
Rbravo555 Jun 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
525 changes: 525 additions & 0 deletions applications/RomApplication/python_scripts/rom_database.py

Large diffs are not rendered by default.

740 changes: 381 additions & 359 deletions applications/RomApplication/python_scripts/rom_manager.py

Large diffs are not rendered by default.

139 changes: 78 additions & 61 deletions applications/RomApplication/python_scripts/rom_nn_trainer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import numpy as np
import pathlib
import json
import sqlite3

import tensorflow as tf
from keras.models import Model
Expand All @@ -14,41 +15,37 @@

class RomNeuralNetworkTrainer(object):

def __init__(self, general_rom_manager_parameters):
def __init__(self, general_rom_manager_parameters, mu_train, mu_validation, data_base):

self.general_rom_manager_parameters = general_rom_manager_parameters
self.nn_parameters = self.general_rom_manager_parameters["ROM"]["ann_enhanced_settings"]
self.nn_parameters.RecursivelyValidateAndAssignDefaults(self._GetDefaultNeuralNetworkParameters())
self.mu_train = mu_train
self.mu_validation = mu_validation
self.data_base = data_base

@classmethod
def _GetDefaultNeuralNetworkParameters(self):
nn_training_parameters = KratosMultiphysics.Parameters("""{
"saved_models_root_path": "rom_data/saved_nn_models/",
"modes":[5,50],
"layers_size":[200,200],
"batch_size":2,
"epochs":800,
"lr_strategy":{
"scheduler": "sgdr",
"base_lr": 0.001,
"additional_params": [1e-4, 10, 400]
},
"training":{
"modes":[5,50],
"layers_size":[200,200],
"batch_size":2,
"epochs":800,
"lr_strategy":{
"scheduler": "sgdr",
"base_lr": 0.001,
"additional_params": [1e-4, 10, 400]
},
"database":{
"training_set": "rom_data/SnapshotsMatrices/fom_snapshots.npy",
"validation_set": "rom_data/SnapshotsMatrices/fom_snapshots_val.npy",
"phi_matrix": "rom_data/RightBasisMatrix.npy",
"sigma_vector": "rom_data/SingularValuesVector.npy"
},
"use_automatic_name": false,
"custom_name": "test_neural_network"
"retrain_if_exists" : false, // If false only one model will be trained for each the mu_train and NN hyperparameters combination
"model_number" : 0 // this part of the parameters will be updated with the number of trained models that exist for the same mu_train and NN hyperparameters combination
},
"online":{
"model_name": "test_neural_network"
"model_number": 0 // out of the models existing for the same parameters, this is the model that will be lauched
}
}""")
return nn_training_parameters

def _CheckNumberOfModes(self,n_inf,n_sup,n_max):
if n_inf >= n_max:
err_msg = f'Specified number of inferior modes ({n_inf}) is higher than or equal to the available ones from the Phi matrix ({n_max}).'
Expand All @@ -57,13 +54,15 @@ def _CheckNumberOfModes(self,n_inf,n_sup,n_max):
err_msg = f'Specified number of superior modes ({n_sup}) is higher than the available ones from the Phi matrix ({n_max}).'
raise Exception(err_msg)

def _GetTrainingData(self, n_inf, n_sup, database_settings):

S_train = np.load(database_settings['training_set'].GetString())
S_val = np.load(database_settings['validation_set'].GetString())
def _GetTrainingData(self, n_inf, n_sup):

phi = np.load(database_settings['phi_matrix'].GetString())
sigma_vec = np.load(database_settings['sigma_vector'].GetString())/np.sqrt(S_train.shape[1])
S_train = self.data_base.get_snapshots_matrix_from_database(self.mu_train, table_name=f'FOM')
S_val = self.data_base.get_snapshots_matrix_from_database(self.mu_validation, table_name=f'FOM')

_, hash_basis = self.data_base.check_if_in_database("RightBasis", self.mu_train)
phi = self.data_base.get_single_numpy_from_database(hash_basis)
_, hash_sigma = self.data_base.check_if_in_database("SingularValues_Solution", self.mu_train)
sigma_vec = self.data_base.get_single_numpy_from_database(hash_sigma)/np.sqrt(len(self.mu_train))

self._CheckNumberOfModes(n_inf,n_sup,sigma_vec.shape[0])

Expand All @@ -76,23 +75,50 @@ def _GetTrainingData(self, n_inf, n_sup, database_settings):
Q_inf_val = (phisig_inv_inf@S_val).T
Q_sup_train = (phisig_inv_sup@S_train).T
Q_sup_val = (phisig_inv_sup@S_val).T
Q_inf_train_original = Q_inf_train.copy()

UseNonConvergedSolutionsGathering = self.general_rom_manager_parameters["ROM"]["use_non_converged_sols"].GetBool()
if UseNonConvergedSolutionsGathering:
#fetching nonconverged sols for enlarginign training samples in ann enhanced prom
conn = sqlite3.connect(self.data_base.database_name)
cursor = conn.cursor()
for mu in self.mu_train:
hash_mu, _ = self.data_base.get_hashed_file_name_for_table('NonconvergedFOM', mu)
cursor.execute(f"SELECT file_name FROM {'NonconvergedFOM'} WHERE file_name = ?", (hash_mu,))
result = cursor.fetchone()
if result:
file_name = result[0]
data = self.data_base.get_single_numpy_from_database(file_name)
max_number_of_nonconverged_sols = 1000 #making sure not all data is contained
number_of_cols = data.shape[1]

if True: #use all data !!! data.shape[1] <= max_number_of_nonconverged_sols:
pass
else:
indices = np.linspace(0, number_of_cols - 1, max_number_of_nonconverged_sols).astype(int)
data = data[:, indices]

Q_inf_train = np.r_[Q_inf_train, (phisig_inv_inf@data).T]
Q_sup_train = np.r_[Q_sup_train, (phisig_inv_sup@data).T]

phisig_norm_matrix = phisig_sup.T @ phisig_sup

rescaling_factor = np.mean(np.square((phisig_inf@Q_inf_train.T)-S_train))
rescaling_factor *= S_train.shape[0]/Q_sup_train.shape[1]
rescaling_factor = np.mean(np.square((phisig_inf@Q_inf_train_original.T)-S_train))
rescaling_factor *= S_train.shape[0]/Q_inf_train_original.shape[1]

return Q_inf_train, Q_inf_val, Q_sup_train, Q_sup_val, phisig_norm_matrix, rescaling_factor

def _GetEvaluationData(self, model_properties):

S_train = np.load(model_properties['database']['training_set'])
S_val = np.load(model_properties['database']['validation_set'])
S_val = self.data_base.get_snapshots_matrix_from_database(self.mu_validation, table_name=f'FOM')

n_inf = model_properties['modes'][0]
n_sup = model_properties['modes'][1]
phi = np.load(model_properties['database']['phi_matrix'])
sigma_vec = np.load(model_properties['database']['sigma_vector'])/np.sqrt(S_train.shape[1])

_, hash_basis = self.data_base.check_if_in_database("RightBasis", self.mu_train)
phi = self.data_base.get_single_numpy_from_database(hash_basis)
_, hash_sigma = self.data_base.check_if_in_database("SingularValues_Solution", self.mu_train)
sigma_vec = self.data_base.get_single_numpy_from_database(hash_sigma)/np.sqrt(len(self.mu_train))

phisig_inv_inf = np.linalg.inv(np.diag(sigma_vec[:n_inf]))@phi[:,:n_inf].T
phisig_inv_sup = np.linalg.inv(np.diag(sigma_vec[n_inf:n_sup]))@phi[:,n_inf:n_sup].T
Expand All @@ -103,13 +129,13 @@ def _GetEvaluationData(self, model_properties):
Q_sup_val = (phisig_inv_sup@S_val).T

return S_val, Q_inf_val, Q_sup_val, phisig_inf, phisig_sup

def _SelectScheduler(self, strategy_name, base_lr, additional_params):

def lr_const_scheduler(epoch, lr):
new_lr= base_lr
return new_lr

def lr_steps_scheduler(epoch, lr):
if epoch==0:
lr=base_lr
Expand All @@ -118,7 +144,7 @@ def lr_steps_scheduler(epoch, lr):
if lr<=additional_params[0]:
lr = additional_params[0]
return lr

def lr_sgdr_scheduler(epoch, lr):
if epoch==0:
new_lr=base_lr
Expand All @@ -131,11 +157,11 @@ def lr_sgdr_scheduler(epoch, lr):
x=np.abs(epoch/cycle_length-cycle)
new_lr = min_lr+(max_lr-min_lr)*0.5*(1+np.cos(x*np.pi))/scale_factor**cycle
return new_lr

schedulers_dict={"const": lr_const_scheduler, "steps": lr_steps_scheduler, "sgdr": lr_sgdr_scheduler}

return schedulers_dict[strategy_name]

def _DefineNetwork(self, n_inf, n_sup, layers_size):
input_layer=layers.Input((n_inf,), dtype=tf.float64)
layer_out=input_layer
Expand All @@ -147,13 +173,13 @@ def _DefineNetwork(self, n_inf, n_sup, layers_size):
return network

def TrainNetwork(self, seed=None):

if seed is not None:
keras_set_random_seed(seed)


nn_training_parameters = self.nn_parameters['training']
nn_training_parameters = self.nn_parameters

n_inf = int(nn_training_parameters['modes'].GetVector()[0])
n_sup = int(nn_training_parameters['modes'].GetVector()[1])
layers_size = nn_training_parameters['layers_size'].GetVector()
Expand All @@ -162,17 +188,13 @@ def TrainNetwork(self, seed=None):
base_lr = nn_training_parameters['lr_strategy']['base_lr'].GetDouble()
lr_additional_params = nn_training_parameters['lr_strategy']['additional_params'].GetVector()
epochs = nn_training_parameters['epochs'].GetInt()

if nn_training_parameters['use_automatic_name'].GetBool():
model_name='NN_model_'+str(n_inf)+'.'+str(n_sup)+'_'+str(layers_size)+'_lr'+lr_scheme+'.'+str(base_lr)+'_batchsize'+str(batch_size)
else:
model_name=nn_training_parameters['custom_name'].GetString()

model_path=pathlib.Path(self.nn_parameters['saved_models_root_path'].GetString()+model_name)
model_name, _ = self.data_base.get_hashed_file_name_for_table("Neural_Network", self.mu_train)
model_path=pathlib.Path(self.data_base.database_root_directory / 'saved_nn_models' / model_name)
model_path.mkdir(parents=True, exist_ok=False)

database_settings = nn_training_parameters['database']
Q_inf_train, Q_inf_val, Q_sup_train, Q_sup_val, phisig_norm_matrix, rescaling_factor = self._GetTrainingData(n_inf, n_sup, database_settings)

Q_inf_train, Q_inf_val, Q_sup_train, Q_sup_val, phisig_norm_matrix, rescaling_factor = self._GetTrainingData(n_inf, n_sup)

network = self._DefineNetwork(n_inf, n_sup, layers_size)

Expand All @@ -189,8 +211,8 @@ def scaled_phinorm_mse_loss(y_true, y_pred):

# history = network.fit(Q_inf_train, Q_sup_train, batch_size=batch_size, epochs=epochs, validation_data=(Q_inf_val,Q_sup_val), shuffle=False, validation_batch_size=1, callbacks=callbacks)
history = network.fit(Q_inf_train, Q_sup_train, batch_size=batch_size, epochs=epochs, validation_data=(Q_inf_val,Q_sup_val), shuffle=True, callbacks=callbacks)


training_parameters_dict = {
"modes":[n_inf,n_sup],
"layers_size":list(layers_size),
Expand All @@ -200,12 +222,6 @@ def scaled_phinorm_mse_loss(y_true, y_pred):
"scheduler": lr_scheme,
"base_lr": base_lr,
"additional_params": list(lr_additional_params)
},
"database":{
"training_set": nn_training_parameters["database"]["training_set"].GetString(),
"validation_set": nn_training_parameters["database"]["validation_set"].GetString(),
"phi_matrix": nn_training_parameters["database"]["phi_matrix"].GetString(),
"sigma_vector": nn_training_parameters["database"]["sigma_vector"].GetString()
}
}

Expand All @@ -220,15 +236,16 @@ def scaled_phinorm_mse_loss(y_true, y_pred):

def EvaluateNetwork(self, model_name):

model_path=pathlib.Path(self.nn_parameters['saved_models_root_path'].GetString()+model_name)
model_name, _ = self.data_base.get_hashed_file_name_for_table("Neural_Network", self.mu_train)
model_path=pathlib.Path(self.data_base.database_root_directory / 'saved_nn_models' / model_name)

with open(str(model_path)+'/train_config.json', "r") as config_file:
model_properties = json.load(config_file)

n_inf = model_properties['modes'][0]
n_sup = model_properties['modes'][1]
layers_size = model_properties['layers_size']

network = self._DefineNetwork(n_inf, n_sup, layers_size)
network.summary()

Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

This file was deleted.

This file was deleted.

3 changes: 3 additions & 0 deletions applications/RomApplication/tests/test_RomApplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from test_save_rom_coefficients_process import TestSaveRomCoefficientsProcess
from test_hrom_training_utility_rom import TestHromTrainingUtilityRom
from test_rom_manager import TestRomManager
from test_rom_database import TestRomDatabase

def AssembleTestSuites():
''' Populates the test suites to run.
Expand Down Expand Up @@ -63,6 +64,8 @@ def AssembleTestSuites():
smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestSaveRomCoefficientsProcess]))
smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestHromTrainingUtilityRom]))
smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestRomManager]))
smallSuite.addTests(KratosUnittest.TestLoader().loadTestsFromTestCases([TestRomDatabase]))


# - testNightly
nightlySuite = suites['nightly']
Expand Down
Loading
Loading