Skip to content

Commit

Permalink
Added hull generator
Browse files Browse the repository at this point in the history
  • Loading branch information
JoeBell committed Mar 4, 2025
1 parent e8845c8 commit 19cf09b
Show file tree
Hide file tree
Showing 2 changed files with 273 additions and 0 deletions.
270 changes: 270 additions & 0 deletions ShipGen/Generate.py
Original file line number Diff line number Diff line change
@@ -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])
3 changes: 3 additions & 0 deletions ShipGen/__init__.py
Original file line number Diff line number Diff line change
@@ -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'))

0 comments on commit 19cf09b

Please sign in to comment.