-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
JoeBell
committed
Mar 4, 2025
1 parent
e8845c8
commit 19cf09b
Showing
2 changed files
with
273 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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')) |