Skip to content

Commit 36604d0

Browse files
committed
Updating RAFT results mapping into FAM and excel export
1 parent cb2bb35 commit 36604d0

File tree

3 files changed

+149
-28
lines changed

3 files changed

+149
-28
lines changed

famodel/famodel_base.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ def __init__(self, id):
6363
self.inst = {'mobilized': False,
6464
'installed': False}
6565

66-
# raft results dictionary
67-
self.raftResults = {}
6866

6967
def isAttached(self, object, end=None):
7068
'''Check if something is attached to this node, even if it's part of

famodel/mooring/mooring.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ def __init__(self, dd=None, subsystem=None, anchor=None,
137137
self.env_impact = {
138138
"disturbedSeabedArea": 0
139139
}
140-
140+
141+
self.raftResults = {}
141142

142143
def update(self, dd=None):
143144
'''Update the Mooring object based on the current state of the design

famodel/project.py

Lines changed: 147 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4447,27 +4447,36 @@ def mapRAFTResults(self, results=None, SFs=True):
44474447
if SFs:
44484448
for moor in self.mooringList.values():
44494449
moor.safety_factors['tension'] = 1e10
4450-
4450+
4451+
# initialize raftResults dictionary in Line [Why isn't line an edge?]
4452+
for moor in self.mooringList.values():
4453+
for line in moor.ss.lineList:
4454+
line.raftResults = {}
4455+
44514456
for iCase in range(nCases):
44524457
i = 0
44534458
for moor in self.mooringList.values():
4454-
for line in moor.ss.lineList:
4455-
line.raftResults = {
4456-
'Tmoor_avg': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_avg'][[i, i+len(self.ms.lineList)]],
4457-
'Tmoor_std': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_std'][[i, i+len(self.ms.lineList)]],
4458-
'Tmoor_min': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_min'][[i, i+len(self.ms.lineList)]],
4459-
'Tmoor_max': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_max'][[i, i+len(self.ms.lineList)]],
4460-
'Tmoor_PSD': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_PSD'][[i, i+len(self.ms.lineList)], :]
4461-
}
4462-
if SFs:
4463-
moor.safety_factors['tension'] = min(moor.safety_factors['tension'], min(line.type['MBL']/line.raftResults['Tmoor_max']))
4464-
moor.safety_factors['analysisType'] = f'(RAFT) MoorMod={self.array.moorMod}'
4459+
moor.raftResults[iCase] = {
4460+
'Tmoor_avg': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_avg'][[i, i+len(self.ms.lineList)]],
4461+
'Tmoor_std': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_std'][[i, i+len(self.ms.lineList)]],
4462+
'Tmoor_min': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_min'][[i, i+len(self.ms.lineList)]],
4463+
'Tmoor_max': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_max'][[i, i+len(self.ms.lineList)]],
4464+
'Tmoor_PSD': self.array.results['case_metrics'][iCase]['array_mooring']['Tmoor_PSD'][[i, i+len(self.ms.lineList)], :]
4465+
}
4466+
if SFs:
4467+
SF = np.zeros((len(moor.ss.lineList)))
4468+
for i, line in enumerate(moor.ss.lineList):
4469+
line_MBL = line.type['MBL']
4470+
SF[i] = line_MBL/np.mean(moor.raftResults[iCase]['Tmoor_avg'])
4471+
4472+
moor.safety_factors['tension'] = min([moor.safety_factors['tension'], min(SF)])
4473+
moor.safety_factors['analysisType'] = f'(RAFT) MoorMod={self.array.moorMod}'
44654474

44664475
i += 1
44674476

44684477
def generateSheets(self, filename):
44694478
"""
4470-
Generates sheets in an Excel workbook with platform and mooring line information.
4479+
Generates sheets in an Excel workbook with RAFT cases, platform, and mooring line information.
44714480
44724481
Parameters
44734482
----------
@@ -4480,7 +4489,32 @@ def generateSheets(self, filename):
44804489
44814490
"""
44824491

4492+
def style_it(sheet, row, col_start, col_end, fill_color="FFFF00"):
4493+
"""
4494+
Applies styling to a range of cells in the given sheet.
4495+
4496+
Parameters
4497+
----------
4498+
sheet : openpyxl.worksheet.worksheet.Worksheet
4499+
The worksheet to apply styling to.
4500+
row : int
4501+
The row number to apply styling to.
4502+
col_start : int
4503+
The starting column number for the range.
4504+
col_end : int
4505+
The ending column number for the range.
4506+
4507+
Returns
4508+
-------
4509+
None
4510+
"""
4511+
for col in range(col_start, col_end + 1):
4512+
cell = sheet.cell(row=row, column=col)
4513+
cell.fill = openpyxl.styles.PatternFill(start_color=fill_color, end_color=fill_color, fill_type="solid")
4514+
cell.font = openpyxl.styles.Font(bold=True)
4515+
44834516
import openpyxl
4517+
from openpyxl.drawing.image import Image
44844518

44854519
if not self.array.results:
44864520
if not self.array.design['cases']:
@@ -4496,33 +4530,121 @@ def generateSheets(self, filename):
44964530
default_sheet = workbook.active
44974531
workbook.remove(default_sheet)
44984532

4533+
if self.array.design:
4534+
# Create a sheet for cases information
4535+
cases_sheet = workbook.create_sheet(title="Cases")
4536+
cases_sheet.append(self.array.design['cases']['keys'])
4537+
for iCase in range(nCases):
4538+
cases_sheet.append(self.array.design['cases']['data'][iCase])
4539+
44994540
# Create a sheet for platforms
45004541
platform_sheet = workbook.create_sheet(title="Platforms")
4501-
platform_sheet.append(["ID", "X", "Y", "Depth", "Case", "Results (Avg)"])
4542+
platform_sheet.append(["ID", "X", "Y", "Depth", "Case", "Results (Avg)", " ", " ", " ", " ", " ", " ", " ", "Results (Std)"])
45024543
platform_sheet.merge_cells(start_row=1, start_column=6, end_row=1, end_column=13)
4503-
platform_sheet.append([" ", " ", " ", " ", " ", "Surge (m)", "Sway (m)", "Heave (m)", "Roll (deg)", "Pitch (deg)", "Yaw (deg)", "NacAcc (m/s^2)", "TwrBend (Nm)"]) #, "RtrSpd (RPM)", "RtrTrq (Nm)", "Power (MW)"
4544+
platform_sheet.merge_cells(start_row=1, start_column=14, end_row=1, end_column=21)
4545+
platform_sheet.append([" ", " ", " ", " ", " ",
4546+
"Surge (m)", "Sway (m)", "Heave (m)", "Roll (deg)", "Pitch (deg)", "Yaw (deg)", "NacAcc (m/s^2)", "TwrBend (kNm)", #, "RtrSpd (RPM)", "RtrTrq (Nm)", "Power (MW)"
4547+
"Surge (m)", "Sway (m)", "Heave (m)", "Roll (deg)", "Pitch (deg)", "Yaw (deg)", "NacAcc (m/s^2)", "TwrBend (kNm)"]) #, "RtrSpd (RPM)", "RtrTrq (Nm)", "Power (MW)"
4548+
platform_sheet.merge_cells(start_row=1, start_column=1, end_row=2, end_column=1)
4549+
platform_sheet.merge_cells(start_row=1, start_column=2, end_row=2, end_column=2)
4550+
platform_sheet.merge_cells(start_row=1, start_column=3, end_row=2, end_column=3)
4551+
platform_sheet.merge_cells(start_row=1, start_column=4, end_row=2, end_column=4)
4552+
platform_sheet.merge_cells(start_row=1, start_column=5, end_row=2, end_column=5)
4553+
surgeMax = float('-inf')
4554+
swayMax = float('-inf')
4555+
rollMax = float('-inf')
4556+
pitchMax = float('-inf')
4557+
nacAccMax = float('-inf')
4558+
twrBendMax = float('-inf')
45044559
for pf in self.platformList.values():
45054560
depth_at_pf = self.getDepthAtLocation(pf.r[0], pf.r[1])
45064561
if hasattr(pf, 'raftResults'):
45074562
for iCase in range(nCases):
45084563
if iCase==0:
4509-
platform_sheet.append([pf.id, round(pf.r[0], 2), round(pf.r[1], 2), round(depth_at_pf, 2), iCase,
4510-
round(pf.raftResults[iCase]['surge_avg'], 2), round(pf.raftResults[iCase]['sway_avg'], 2), round(pf.raftResults[iCase]['heave_avg'], 2),
4511-
round(pf.raftResults[iCase]['roll_avg'], 2), round(pf.raftResults[iCase]['pitch_avg'], 2), round(pf.raftResults[iCase]['yaw_avg'], 2),
4512-
round(pf.raftResults[iCase]['AxRNA_avg'][0], 2), round(pf.raftResults[iCase]['Mbase_avg'][0], 2)]) #, round(pf.raftResults[iCase]['omega_avg'][0], 2), round(pf.raftResults[iCase]['torque_avg'][0], 2), round(pf.raftResults[iCase]['power_avg'][0]*1e-6, 2)])
4564+
platform_sheet.append([pf.id, round(pf.r[0], 3), round(pf.r[1], 3), round(depth_at_pf, 3), iCase,
4565+
round(pf.raftResults[iCase]['surge_avg'], 3), round(pf.raftResults[iCase]['sway_avg'], 3), round(pf.raftResults[iCase]['heave_avg'], 3),
4566+
round(pf.raftResults[iCase]['roll_avg'], 3), round(pf.raftResults[iCase]['pitch_avg'], 3), round(pf.raftResults[iCase]['yaw_avg'], 3),
4567+
round(pf.raftResults[iCase]['AxRNA_avg'][0], 3), round(pf.raftResults[iCase]['Mbase_avg'][0]/1e3, 3), #, round(pf.raftResults[iCase]['omega_avg'][0], 3), round(pf.raftResults[iCase]['torque_avg'][0], 3), round(pf.raftResults[iCase]['power_avg'][0]*1e-6, 3)])
4568+
round(pf.raftResults[iCase]['surge_std'], 3), round(pf.raftResults[iCase]['sway_std'], 3), round(pf.raftResults[iCase]['heave_std'], 3),
4569+
round(pf.raftResults[iCase]['roll_std'], 3), round(pf.raftResults[iCase]['pitch_std'], 3), round(pf.raftResults[iCase]['yaw_std'], 3),
4570+
round(pf.raftResults[iCase]['AxRNA_std'][0], 3), round(pf.raftResults[iCase]['Mbase_std'][0]/1e3, 3)]) #, round(pf.raftResults[iCase]['omega_avg'][0], 3), round(pf.raftResults[iCase]['torque_avg'][0], 3), round(pf.raftResults[iCase]['power_avg'][0]*1e-6, 3)])
45134571
else:
45144572
platform_sheet.append([" ", " ", " ", " ", iCase,
4515-
round(pf.raftResults[iCase]['surge_avg'], 2), round(pf.raftResults[iCase]['sway_avg'], 2), round(pf.raftResults[iCase]['heave_avg'], 2),
4516-
round(pf.raftResults[iCase]['roll_avg'], 2), round(pf.raftResults[iCase]['pitch_avg'], 2), round(pf.raftResults[iCase]['yaw_avg'], 2),
4517-
round(pf.raftResults[iCase]['AxRNA_avg'][0], 2), round(pf.raftResults[iCase]['Mbase_avg'][0], 2)]) #, round(pf.raftResults[iCase]['omega_avg'][0], 2), round(pf.raftResults[iCase]['torque_avg'][0], 2), round(pf.raftResults[iCase]['power_avg'][0]*1e-6, 2)])
4573+
round(pf.raftResults[iCase]['surge_avg'], 3), round(pf.raftResults[iCase]['sway_avg'], 3), round(pf.raftResults[iCase]['heave_avg'], 3),
4574+
round(pf.raftResults[iCase]['roll_avg'], 3), round(pf.raftResults[iCase]['pitch_avg'], 3), round(pf.raftResults[iCase]['yaw_avg'], 3),
4575+
round(pf.raftResults[iCase]['AxRNA_avg'][0], 3), round(pf.raftResults[iCase]['Mbase_avg'][0]/1e3, 3), #, round(pf.raftResults[iCase]['omega_avg'][0], 3), round(pf.raftResults[iCase]['torque_avg'][0], 3), round(pf.raftResults[iCase]['power_avg'][0]*1e-6, 3)])
4576+
round(pf.raftResults[iCase]['surge_std'], 3), round(pf.raftResults[iCase]['sway_std'], 3), round(pf.raftResults[iCase]['heave_std'], 3),
4577+
round(pf.raftResults[iCase]['roll_std'], 3), round(pf.raftResults[iCase]['pitch_std'], 3), round(pf.raftResults[iCase]['yaw_std'], 3),
4578+
round(pf.raftResults[iCase]['AxRNA_std'][0], 3), round(pf.raftResults[iCase]['Mbase_std'][0]/1e3, 3)]) #, round(pf.raftResults[iCase]['omega_avg'][0], 3), round(pf.raftResults[iCase]['torque_avg'][0], 3), round(pf.raftResults[iCase]['power_avg'][0]*1e-6, 3)])
4579+
# Update min and max values
4580+
surgeMax = max(surgeMax, abs(pf.raftResults[iCase]['surge_avg'])); swayMax = max(swayMax, abs(pf.raftResults[iCase]['sway_avg']))
4581+
rollMax = max(rollMax, abs(pf.raftResults[iCase]['roll_avg'])); pitchMax = max(pitchMax, abs(pf.raftResults[iCase]['pitch_avg']))
4582+
nacAccMax = max(nacAccMax, abs(pf.raftResults[iCase]['AxRNA_avg'][0])); twrBendMax = max(twrBendMax, abs(pf.raftResults[iCase]['Mbase_avg'][0]/1e3))
4583+
4584+
platform_sheet.merge_cells(start_row=platform_sheet.max_row-nCases+1, start_column=1, end_row=platform_sheet.max_row, end_column=1)
4585+
platform_sheet.merge_cells(start_row=platform_sheet.max_row-nCases+1, start_column=2, end_row=platform_sheet.max_row, end_column=2)
4586+
platform_sheet.merge_cells(start_row=platform_sheet.max_row-nCases+1, start_column=3, end_row=platform_sheet.max_row, end_column=3)
4587+
platform_sheet.merge_cells(start_row=platform_sheet.max_row-nCases+1, start_column=4, end_row=platform_sheet.max_row, end_column=4)
45184588
else:
4519-
platform_sheet.append([pf.id, round(pf.r[0], 2), round(pf.r[1], 2), round(depth_at_pf, 2)])
4589+
platform_sheet.append([pf.id, round(pf.r[0], 3), round(pf.r[1], 3), round(depth_at_pf, 3)])
4590+
4591+
platform_sheet.append(["----------------------"])
4592+
platform_sheet.append(["Highest average values"])
4593+
for cell in platform_sheet[platform_sheet.max_row]:
4594+
cell.font = openpyxl.styles.Font(bold=True)
4595+
4596+
platform_sheet.append(["Surge (m)", "Sway (m)", "Roll (deg)", "Pitch (deg)", "NacAcc (m/s^2)", "TwrBend (Nm)"])
4597+
platform_sheet.append([round(surgeMax, 3), round(swayMax, 3), round(rollMax, 3), round(pitchMax, 3), round(nacAccMax, 3), round(twrBendMax, 3)])
4598+
# style maximum values (bold and italic)
4599+
for cell in platform_sheet[platform_sheet.max_row]:
4600+
cell.font = openpyxl.styles.Font(bold=True, italic=True)
45204601

45214602
# Create a sheet for mooring lines
45224603
mooring_sheet = workbook.create_sheet(title="Mooring Lines")
4523-
mooring_sheet.append(["ID", "endA", "endB", "Shrd", "Safety Factors", "Fid Level"])
4604+
mooring_sheet.append(["ID", "endA", "endB", "Shrd", "Safety Factors", "Fid Level", "Case", "Avg EndA Tension (kN)", "Std EndA Tension (kN)", "Avg EndB Tension (kN)", "Std EndB Tension (kN)"])
45244605
for moor in self.mooringList.values():
4525-
mooring_sheet.append([moor.id, moor.attached_to[0].id, moor.attached_to[1].id, moor.shared, round(moor.safety_factors['tension'], 2), moor.safety_factors['analysisType']])
4606+
if hasattr(moor, 'raftResults'):
4607+
for iCase in range(nCases):
4608+
if iCase==0:
4609+
mooring_sheet.append([moor.id, moor.attached_to[0].id, moor.attached_to[1].id, moor.shared, round(moor.safety_factors['tension'], 3), moor.safety_factors['analysisType'], iCase,
4610+
round(moor.raftResults[iCase]['Tmoor_avg'][0], 3)/1e3, round(moor.raftResults[iCase]['Tmoor_std'][0], 3)/1e3,
4611+
round(moor.raftResults[iCase]['Tmoor_avg'][1], 3)/1e3, round(moor.raftResults[iCase]['Tmoor_std'][1], 3)/1e3])
4612+
if moor.safety_factors['tension']<2.0:
4613+
style_it(mooring_sheet, mooring_sheet.max_row, 1, 6, fill_color="FF0000")
4614+
4615+
else:
4616+
mooring_sheet.append([" ", " ", " ", " ", " ", " ", iCase,
4617+
round(moor.raftResults[iCase]['Tmoor_avg'][0], 3)/1e3, round(moor.raftResults[iCase]['Tmoor_std'][0], 3)/1e3,
4618+
round(moor.raftResults[iCase]['Tmoor_avg'][1], 3)/1e3, round(moor.raftResults[iCase]['Tmoor_std'][1], 3)/1e3])
4619+
if np.any(moor.raftResults[iCase]['Tmoor_avg']/1e3 < 100):
4620+
style_it(mooring_sheet, mooring_sheet.max_row, 7, mooring_sheet.max_column, fill_color="FFFF00")
4621+
mooring_sheet.merge_cells(start_row=mooring_sheet.max_row-nCases+1, start_column=1, end_row=mooring_sheet.max_row, end_column=1)
4622+
mooring_sheet.merge_cells(start_row=mooring_sheet.max_row-nCases+1, start_column=2, end_row=mooring_sheet.max_row, end_column=2)
4623+
mooring_sheet.merge_cells(start_row=mooring_sheet.max_row-nCases+1, start_column=3, end_row=mooring_sheet.max_row, end_column=3)
4624+
mooring_sheet.merge_cells(start_row=mooring_sheet.max_row-nCases+1, start_column=4, end_row=mooring_sheet.max_row, end_column=4)
4625+
mooring_sheet.merge_cells(start_row=mooring_sheet.max_row-nCases+1, start_column=5, end_row=mooring_sheet.max_row, end_column=5)
4626+
mooring_sheet.merge_cells(start_row=mooring_sheet.max_row-nCases+1, start_column=6, end_row=mooring_sheet.max_row, end_column=6)
4627+
else:
4628+
mooring_sheet.append([moor.id, moor.attached_to[0].id, moor.attached_to[1].id, moor.shared, round(moor.safety_factors['tension'], 3), moor.safety_factors['analysisType']])
4629+
4630+
# Create a sheet for a 2D Plot
4631+
plot_sheet_2D = workbook.create_sheet(title="2D Plot")
4632+
fig, ax = plt.subplots()
4633+
ax = self.plot2d(ax=ax, plot_boundary=False, plot_bathymetry=True)
4634+
filenameFolder = os.path.dirname(filename)
4635+
imagePath = os.path.join(filenameFolder, 'temp_plot_2D.png')
4636+
fig.savefig(imagePath, dpi=300)
4637+
img = Image(imagePath)
4638+
plot_sheet_2D.add_image(img, 'A1')
4639+
4640+
# Create a sheet for a 3D Plot
4641+
plot_sheet_3D = workbook.create_sheet(title="3D Plot")
4642+
fig, ax = plt.subplots(subplot_kw={'projection': '3d'})
4643+
ax = self.plot3d(ax=ax, fowt=True, draw_boundary=True, boundary_on_bath=True, draw_bathymetry=True)
4644+
imagePath = os.path.join(filenameFolder, 'temp_plot_3D.png')
4645+
fig.savefig(imagePath, dpi=300)
4646+
img = Image(imagePath)
4647+
plot_sheet_3D.add_image(img, 'A1')
45264648

45274649
# Save the workbook
45284650
workbook.save(filename)

0 commit comments

Comments
 (0)