diff --git a/ShipGen/Generate.py b/ShipGen/Generate.py new file mode 100644 index 0000000..845b26c --- /dev/null +++ b/ShipGen/Generate.py @@ -0,0 +1,270 @@ +import os + +import numpy as np +from tqdm import tqdm +import math +import matplotlib.pyplot as plt +import torch +import torch.nn as nn +import torch.nn.functional as F +from .tools import Guided_Cond_DDPM_Tools as GC_DDPM +from .__init__ import data_path, trained_models_path + +from sklearn.decomposition import PCA # type: ignore + +import matplotlib.pyplot as plt + +from .tools.HullParameterization import Hull_Parameterization as HP + +device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +np.set_printoptions(suppress=True) # don't use scientific notation + +# Load in the Data: + +#Step 1: Load in the data +DesVec = np.load(f'{data_path}/DesVec_82k.npy', allow_pickle=True) + +DesVec_neg = np.load(f'{data_path}/Negative_DesVec_82k.npy', allow_pickle=True) + +# Now lets clean up X + +idx_BBFactors = [33,34,35,36,37] +idx_BB = 31 + +idx_SBFactors = [38,39,40,41,42,43,44] +idx_SB = 32 + +for i in range(0,len(DesVec)): + DesVec[i,idx_BBFactors] = DesVec[i,idx_BB] * DesVec[i,idx_BBFactors] + DesVec[i,idx_SBFactors] = DesVec[i,idx_SB] * DesVec[i,idx_SBFactors] + + +Y = np.load(f'{data_path}/GeometricMeasures.npy', allow_pickle=True) + +LenRatios = np.load(f'{data_path}/Length_Ratios.npy', allow_pickle=True) + +X_LIMITS = np.load(f'{data_path}/X_LIMITS.npy') + +X_lower_lim = [X_LIMITS[:,0].tolist()] +X_upper_lim = [X_LIMITS[:,1].tolist()] + +#Set up Conditioning Vectors: +num_WL_Steps = 101 + +VolVec = np.log10(Y[:,1*num_WL_Steps:2*num_WL_Steps]) +idx = np.where(np.isnan(VolVec)) + +VolVec[idx] = -6.0 #fix nan to dummy value + +DdVec = DesVec[:,4] +BOAVec = np.amax(LenRatios[:,1:3], axis=1) + +def create_network() -> GC_DDPM.GuidedDiffusionEnv: + # Set up the file for architecting the network, diffusion parameters, and training + + DDPM_Dict = { + 'xdim' : len(DesVec[0])-1, # Dimension of parametric design vector + 'datalength': len(DesVec), # number of samples + 'X_LL' : X_lower_lim, # lower limits of parametric design vector variables + 'X_UL' : X_upper_lim, + 'ydim': 0, # Number of objectives + 'cdim': 4, # number of conditioning inputs + 'gamma' : 0.2, # weight of feasibility guidance for guided sampling + 'lambda': [0.3,0.3], # weight of drag guidance for guided sampling + #'lambdas': [1,1,1,1,1,1,1], # dummy variable for performance guided sampling + 'tdim': 128, # dimension of latent variable + 'net': [1024,1024,1024,1024], # network architecture + 'batch_size': 1024, # batch size + 'Training_Epochs': 10000, # number of training epochs + 'Diffusion_Timesteps': 1000, # number of diffusion timesteps + 'lr' : 0.00025, # learning rate + 'weight_decay': 0.0, # weight decay + 'device_name': device} # gpu device name + + Classify_Dict = { + 'xdim' : len(DesVec[0])-1, + 'cdim': 1, + 'tdim': 128, + 'net': [64,64,64], + 'Training_Epochs': 150000, + 'device_name': device} + + nodes = 512 + Drag_Reg_Dict = { + 'xdim' : len(DesVec[0])-1, # Dimension of parametric design vector + 'ydim': 1, # trains regression model for each objective + 'tdim': nodes, # dimension of latent variable + 'net': [nodes,nodes,nodes,nodes], # network architecture + 'Training_Epochs': 50000, #30000 # number of training epochs + 'batch_size': 1024, # batch size + 'Model_Label': 'Regressor_CT', # labels for regressors + 'lr' : 0.001, # learning rate + 'weight_decay': 0.0, # weight decay + 'device_name': device} + + nodes = 256 + LOA_wBulb_Reg_Dict = { + 'xdim' : len(DesVec[0])-1, # Dimension of parametric design vector + 'ydim': 1, # trains regression model for each objective + 'tdim': nodes, # dimension of latent variable + 'net': [nodes,nodes,nodes], # network architecture + 'Training_Epochs': 150000, # number of training epochs + 'batch_size': 1024, # batch size + 'Model_Label': 'Regressor_LOA_wBulb', # labels for regressors + + 'lr' : 0.001, # learning rate + 'weight_decay': 0.0, # weight decay + 'device_name': device} + + WL_Reg_Dict = { + "xdim": len(DesVec[0]), + "ydim": 1, + "tdim": 512, + "net": [512, 512, 512], + "Training_Epochs": 30000, + "batch_size": 1024, + "Model_Label": + "Regressor_WL", + "lr": 0.001, + "weight_decay": 0.0, + "device_name": device} + + Vol_Reg_Dict = { + "xdim": len(DesVec[0]), + "ydim": 1, + "tdim": 512, + "net": [512, 512, 512], + "Training_Epochs": 30000, + "batch_size": 1024, + "Model_Label": "Regressor_WL", + "lr": 0.001, + "weight_decay": 0.0, + "device_name": device} + + T = GC_DDPM.GuidedDiffusionEnv(DDPM_Dict, + Classify_Dict, + Drag_Reg_Dict, + LOA_wBulb_Reg_Dict, + WL_Reg_Dict, + Vol_Reg_Dict, + X= DesVec[:,1:], + X_neg= DesVec_neg, + VolVec = VolVec, + BOAVec = BOAVec, + DdVec = DdVec) + + diffusion_path = f'{trained_models_path}/CShipGen_diffusion.pth' + T.load_trained_diffusion_model(diffusion_path) + classifier_path = f'{trained_models_path}/Constraint_Classifier_150000Epochs.pth' + T.load_trained_classifier_model(classifier_path) + + PATHS = [f'{trained_models_path}/Regressor_CT.pth', + f'{trained_models_path}/Regressor_LOA_wBulb.pth', + f'{trained_models_path}/Regressor_WL.pth', + f'{trained_models_path}/Regressor_Vol.pth'] + + T.load_trained_Drag_regression_models(PATHS) + return T +T = create_network() + +class ShipCharacteristics: + LOA:float + Beam:float + Draft:float + Depth:float + Volume:float + U:float + def __init__(self, + LOA:float, + Beam:float, + Draft:float, + Depth:float, + Volume:float, + U:float): + self.LOA = LOA + self.Beam = Beam + self.Draft = Draft + self.Depth = Depth + self.Volume = Volume + self.U = U + def as_array(self) -> np.ndarray: + return np.array([self.LOA, self.Beam, self.Draft, self.Depth, self.Volume, self.U]) + +def check_feasibility(x_samples:np.ndarray): + for i in range(0,len(x_samples)): + + x_samples[i,idx_BB] = (x_samples[i,idx_BB] + 0.5) // 1 #int rounds to 1 or 0 + x_samples[i,idx_SB] = (x_samples[i,idx_SB] + 0.5) // 1 #int rounds to 1 or 0 + + + x_samples[i,idx_BBFactors] = x_samples[i,idx_BB] * x_samples[i,idx_BBFactors] + x_samples[i,idx_SBFactors] = x_samples[i,idx_SB] * x_samples[i,idx_SBFactors] + + #Check the constraint violations for the sampled designs + valid_idx:list[int] = [] + + for i in tqdm(range(0,len(x_samples))): + hull = HP(x_samples[i]) + if sum(hull.input_Constraints() > 0) == 0: + valid_idx.append(i) + return valid_idx + +def generate_hulls(final_count:int, + reject_count:int|None = None, + characteristics:ShipCharacteristics|None = None, + reject_ratio:float = 9): + if characteristics is None: + Ship = np.array([333, 42.624, 11.28, 29.064, 97561,16]) + else: Ship = characteristics.as_array() + if reject_count is None: num_samples = final_count * (reject_ratio + 1) + else: num_samples = final_count + reject_count + + LOA = Ship[0] #in meters + BoL = Ship[1]/LOA #beam to length ratio + ToD = Ship[2]/Ship[3] #Draft to depth ratio + DoL = Ship[3]/LOA #Depth to length ratio + Vol = np.log10(Ship[4]/LOA**3) # to normalize Volume by LOA**3 + + U = Ship[5] # 12.86 #m/s = 25 knots + + dim_d = np.array([[ToD, U, LOA]]) #Drag_conditioning is [ToD, U(m/s), LOA (m)] + + drag_cond = np.repeat(dim_d, num_samples, axis=0) #reapeat + #print(cond.shape) + dim_g = np.array([[ToD, BoL, DoL, Vol]]) + + geom_cond = np.repeat(dim_g, num_samples, axis=0) #reapeat + #print(cond.shape) + + x_samples, unnorm = T.gen_vol_drag_guided_samples(geom_cond, drag_cond) + + + Rt_guidance = T.Predict_Drag(unnorm, drag_cond) + Drag_Guidance = np.mean(Rt_guidance) + + + + + path = "./Hulls/" + + label = 'Hull_' + + isExist = os.path.exists(path) + if not isExist: + os.makedirs(path) + + valid_idx = check_feasibility(x_samples) + + idxs = np.argsort(Rt_guidance[valid_idx].flatten()) + + for i in tqdm(range(0,10)): + Hull = HP(x_samples[valid_idx[idxs[i]]]) + #make the .stl file of the hull: + strpath = path+label + '_' + str(valid_idx[idxs[i]]) + try: + mesh = Hull.gen_stl(NUM_WL=47, PointsPerWL=151, bit_AddTransom = 1, bit_AddDeckLid = 1, bit_RefineBowAndStern = 1,namepath = strpath) + except: + print('Error at hull {}'.format(valid_idx[idxs[i]])) + + idx_min_pred_drag = np.argmin(Rt_guidance[valid_idx]) \ No newline at end of file diff --git a/ShipGen/__init__.py b/ShipGen/__init__.py index e69de29..3a08d65 100644 --- a/ShipGen/__init__.py +++ b/ShipGen/__init__.py @@ -0,0 +1,3 @@ +import os +data_path = os.path.normpath(os.path.join(__file__,'../data')) +trained_models_path = os.path.normpath(os.path.join(__file__,'../TrainedModels')) \ No newline at end of file