Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
42 changes: 42 additions & 0 deletions Code/tests/pythontests/resources/poiseuille_flow_test.pr2
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
DurationSeconds: 0x1.4000000000000p+2
Iolets:
- Centre:
x: 0x0.0p+0
y: 0x0.0p+0
z: -0x1.e000000000000p+4
Name: Inlet1
Normal:
x: 0x0.0p+0
y: 0x0.0p+0
z: 0x1.0000000000000p+0
Pressure:
x: 0x1.0000000000000p+4
y: 0x0.0p+0
z: 0x0.0p+0
Radius: 0x1.8000000000000p-1
Type: Inlet
- Centre:
x: 0x0.0p+0
y: 0x0.0p+0
z: 0x1.e000000000000p+4
Name: Outlet1
Normal:
x: 0x0.0p+0
y: 0x0.0p+0
z: -0x1.0000000000000p+0
Pressure:
x: 0x0.0p+0
y: 0x0.0p+0
z: 0x0.0p+0
Radius: 0x1.8000000000000p-1
Type: Outlet
OutputGeometryFile: poiseuille_flow_test.gmy
OutputXmlFile: poiseuille_flow_test.xml
SeedPoint:
x: -0x1.00da93eaa8180p-1
y: -0x1.156ab416a2440p-6
z: -0x1.f88444ad1efccp+3
StlFile: poiseuille_flow_test.stl
StlFileUnitId: 1
TimeStepSeconds: 0x1.a36e2eb1c432dp-14
VoxelSize: 0x1.568f2c0000000p-3
88 changes: 83 additions & 5 deletions geometry-tool/HlbGmyTool/Model/Profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,49 @@
from ..Util.Observer import Observable
from .SideLengthCalculator import AverageSideLengthCalculator
from .Vector import Vector
from .Iolets import ObservableListOfIolets, IoletLoader
# from .Iolets import ObservableListOfIolets, IoletLoader
from .Iolets import ObservableListOfIolets, IoletLoader, Inlet, Outlet # ← added Inlet, Outlet

import types # required for dynamic module creation

class FakeUnpickler(pickle.Unpickler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._HST = types.ModuleType("HemeLbSetupTool")
self._classes = {}

def _get_or_make_mod(self, moduleName):
parts = moduleName.split(".")
hst = parts.pop(0)
assert hst == "HemeLbSetupTool"
full = hst
cur = self._HST
while parts:
name = parts.pop(0)
if not hasattr(cur, name):
mod = types.ModuleType(f"{full}.{name}")
mod.__package__ = full
full = mod.__name__
setattr(cur, name, mod)
cur = getattr(cur, name)
return cur

def _get_or_make_class(self, mod, className):
try:
return getattr(mod, className)
except AttributeError:
def __up__(this):
return this # no-op upgrade
fake = type(className, (object,), {"__module__": mod.__name__, "__up__": __up__})
setattr(mod, className, fake)
return fake

def find_class(self, moduleName, className):
if moduleName.startswith("HemeLbSetupTool"):
mod = self._get_or_make_mod(moduleName)
return self._get_or_make_class(mod, className)
return super().find_class(moduleName, className)



class LengthUnit(Observable):
Expand Down Expand Up @@ -205,9 +247,45 @@ def LoadProfileV2(self, filename):

def LoadProfileV1(self, filename):
with open(filename, "rb") as f:
restored = pickle.Unpickler(f, fix_imports=True).load()
restored._ResetPaths(filename)
self.CloneFrom(restored)
# restored = pickle.Unpickler(f, fix_imports=True).load()
restored_fake = FakeUnpickler(f).load()
halfway = restored_fake.__up__() # convert fake object to a dict-like profile object

# Manually assign fields instead of using CloneFrom(), to avoid constructor issues
for attr in Profile._Args:
val = getattr(halfway, attr, None)

if attr == 'SeedPoint' and val is not None:
# Upgrade legacy vector to real Vector instance
self.SeedPoint = Vector(val.x, val.y, val.z)

elif attr == 'Iolets' and val is not None:
# Upgrade list of fake Inlet/Outlet objects to real ones
real_iolets = ObservableListOfIolets()
for io in val:
# Choose correct type (Inlet or Outlet)
inlet_or_outlet = Inlet() if getattr(io, 'Name', '').startswith("Inlet") else Outlet()

# Set required fields
inlet_or_outlet.Name = getattr(io, 'Name', None)
inlet_or_outlet.Radius = getattr(io, 'Radius', None)
inlet_or_outlet.Centre = Vector(io.Centre.x, io.Centre.y, io.Centre.z)
inlet_or_outlet.Normal = Vector(io.Normal.x, io.Normal.y, io.Normal.z)
inlet_or_outlet.Pressure = Vector(io.Pressure.x, io.Pressure.y, io.Pressure.z)

real_iolets.append(inlet_or_outlet)

self.Iolets = real_iolets

elif val is not None:
# Default assignment for all other attributes
setattr(self, attr, val)

# Adjust file paths to be relative to the profile file
self._ResetPaths(filename)

# restored._ResetPaths(filename)
# self.CloneFrom(restored)
return

def _ResetPaths(self, filename):
Expand Down Expand Up @@ -280,4 +358,4 @@ def IsFileValid(path, ext=None, exists=None):
if ending != ext:
return False
pass
return True
return True