this is my code:
# read stl files to make geometry
point_path = to_absolute_path("examples/aneurysm/stl_files")
inlet_mesh = Tessellation.from_stl(
point_path + "/aneurysm_inlet.stl", airtight=False
)
outlet_mesh = Tessellation.from_stl(
point_path + "/aneurysm_outlet.stl", airtight=False
)
noslip_mesh = Tessellation.from_stl(
point_path + "/aneurysm_noslip.stl", airtight=False
)
integral_mesh = Tessellation.from_stl(
point_path + "/aneurysm_integral.stl", airtight=False
)
interior_mesh = Tessellation.from_stl(
point_path + "/aneurysm_closed.stl", airtight=True
)
# params
nu = 0.025
inlet_vel = 1.5
# time window parameters
time_window_size = 1.0
t_symbol = Symbol("t")
time_range = {t_symbol: (0, time_window_size)}
nr_time_windows = 10
# inlet velocity profile
def circular_parabola(x, y, z, center, normal, radius, max_vel):
centered_x = x - center[0]
centered_y = y - center[1]
centered_z = z - center[2]
distance = sqrt(centered_x ** 2 + centered_y ** 2 + centered_z ** 2)
parabola = max_vel * Max((1 - (distance / radius) ** 2), 0)
return normal[0] * parabola, normal[1] * parabola, normal[2] * parabola
# normalize meshes
def normalize_mesh(mesh, center, scale):
mesh = mesh.translate([-c for c in center])
mesh = mesh.scale(scale)
return mesh
# normalize invars
def normalize_invar(invar, center, scale, dims=2):
invar["x"] -= center[0]
invar["y"] -= center[1]
invar["z"] -= center[2]
invar["x"] *= scale
invar["y"] *= scale
invar["z"] *= scale
if "area" in invar.keys():
invar["area"] *= scale ** dims
return invar
# scale and normalize mesh and openfoam data
center = (-18.40381048596882, -50.285383353981196, 12.848136936899031)
scale = 0.4
inlet_mesh = normalize_mesh(inlet_mesh, center, scale)
outlet_mesh = normalize_mesh(outlet_mesh, center, scale)
noslip_mesh = normalize_mesh(noslip_mesh, center, scale)
integral_mesh = normalize_mesh(integral_mesh, center, scale)
interior_mesh = normalize_mesh(interior_mesh, center, scale)
# geom params
inlet_normal = (0.8526, -0.428, 0.299)
inlet_area = 21.1284 * (scale ** 2)
inlet_center = (-4.24298030045776, 4.082857101816247, -4.637790193399717)
inlet_radius = np.sqrt(inlet_area / np.pi)
outlet_normal = (0.33179, 0.43424, 0.83747)
outlet_area = 12.0773 * (scale ** 2)
outlet_radius = np.sqrt(outlet_area / np.pi)
# make list of nodes to unroll graph on
ns = NavierStokes(nu=nu * scale, rho=1.0, dim=3, time=True)
normal_dot_vel = NormalDotVec(["u", "v", "w"])
flow_net = FullyConnectedArch(
input_keys=[Key("x"), Key("y"), Key("z"), Key("t")],
output_keys=[Key("u"), Key("v"), Key("w"), Key("p")],
layer_size=256,
)
time_window_net = MovingTimeWindowArch(flow_net, time_window_size)
nodes = (
ns.make_nodes()
+ normal_dot_vel.make_nodes()
+[time_window_net.make_node(name="time_window_network")]
)
x = Symbol("x")
y = Symbol("y")
z = Symbol("z")
t = Symbol("t")
# make initial condition domain
ic_domain = Domain("initial_conditions")
# make moving window domain
window_domain = Domain("window")
# add constraints to solver
# inlet
u, v, w = circular_parabola(
Symbol("x"),
Symbol("y"),
Symbol("z"),
center=inlet_center,
normal=inlet_normal,
radius=inlet_radius,
max_vel=inlet_vel,
)
# make initial condition
ic = PointwiseInteriorConstraint(
nodes=nodes,
geometry=interior_mesh,
outvar={
"u":0,
"v": 0,
"w": 0,
"p": 0,
},
batch_size=cfg.batch_size.initial_condition,
lambda_weighting={"u": 100, "v": 100, "w": 100, "p": 100},
parameterization={t_symbol: 0},
)
ic_domain.add_constraint(ic, name="ic")
# make constraint for matching previous windows initial condition
ic = PointwiseInteriorConstraint(
nodes=nodes,
geometry=interior_mesh,
outvar={"u_prev_step_diff": 0, "v_prev_step_diff": 0, "w_prev_step_diff": 0},
batch_size=cfg.batch_size.interior,
lambda_weighting={
"u_prev_step_diff": 100,
"v_prev_step_diff": 100,
"w_prev_step_diff": 100,
},
parameterization={t_symbol: 0},
)
window_domain.add_constraint(ic, name="ic")
inlet = PointwiseBoundaryConstraint(
nodes=nodes,
geometry=inlet_mesh,
outvar={"u": u, "v": v, "w": w},
parameterization=time_range,
batch_size=cfg.batch_size.inlet,
)
ic_domain.add_constraint(inlet, name="inlet")
window_domain.add_constraint(inlet, "inlet")
# outlet
outlet = PointwiseBoundaryConstraint(
nodes=nodes,
geometry=outlet_mesh,
outvar={"p": 0},
parameterization=time_range,
batch_size=cfg.batch_size.outlet,
)
ic_domain.add_constraint(outlet, name="outlet")
window_domain.add_constraint(outlet, "outlet")
# no slip
no_slip = PointwiseBoundaryConstraint(
nodes=nodes,
geometry=noslip_mesh,
outvar={"u": 0, "v": 0, "w": 0},
parameterization=time_range,
batch_size=cfg.batch_size.no_slip,
)
ic_domain.add_constraint(no_slip, name="no_slip")
window_domain.add_constraint(no_slip, "no_slip")
# interior
interior = PointwiseInteriorConstraint(
nodes=nodes,
geometry=interior_mesh,
outvar={"continuity": 0, "momentum_x": 0, "momentum_y": 0, "momentum_z": 0},
batch_size=cfg.batch_size.interior,
parameterization=time_range,
)
ic_domain.add_constraint(interior, name="interior")
window_domain.add_constraint(interior, "interior")
# Integral Continuity 1
integral_continuity1 = IntegralBoundaryConstraint(
nodes=nodes,
geometry=outlet_mesh,
outvar={"normal_dot_vel": 2.540},
batch_size=1,
parameterization=time_range,
integral_batch_size=cfg.batch_size.integral_continuity,
lambda_weighting={"normal_dot_vel": 0.1},
)
ic_domain.add_constraint(integral_continuity1, name="integral_continuity1")
window_domain.add_constraint(integral_continuity1, "integral_continuity1")
# Integral Continuity 2
integral_continuity2 = IntegralBoundaryConstraint(
nodes=nodes,
geometry=integral_mesh,
outvar={"normal_dot_vel": -2.540},
batch_size=1,
parameterization=time_range,
integral_batch_size=cfg.batch_size.integral_continuity,
lambda_weighting={"normal_dot_vel": 0.1},
)
ic_domain.add_constraint(integral_continuity2, name="integral_continuity2")
window_domain.add_constraint(integral_continuity2, "integral_continuity2")
# Find the bounds
point_path = to_absolute_path("examples/aneurysm/stl_files/aneurysm_closed.stl")
recb = mesh.Mesh.from_file(point_path)
min_bound = np.min(recb.points, axis=0)
max_bound = np.max(recb.points, axis=0)
bounds = {
"x": (min_bound[0], max_bound[0]),
"y": (min_bound[1], max_bound[1]),
"z": (min_bound[2], max_bound[2]),
}
# add validation data
mapping = {
"Points:0": "x",
"Points:1": "y",
"Points:2": "z",
"U:0": "u",
"U:1": "v",
"U:2": "w",
"p": "p",
}
def mask_fn(**invar):
invar_s = {
key: value for key, value in invar.items() if key in ["x", "y", "z"]
}
# TODO... lambda x, y, z: self.interior_mesh.sdf({"x": x, "y": y, "z": z}, {})["sdf"]
invar_p = {
key: value for key, value in invar.items() if key not in ["x", "y", "z"]
}
sdf = interior_mesh.sdf(invar_s, invar_p)
return np.less(sdf["sdf"], 0)
voxel_inferencer = VoxelInferencer(
bounds = [[min_bound[0], max_bound[0]], [min_bound[1], max_bound[1]], [min_bound[2], max_bound[2]]],
npoints = [128, 128, 128],
nodes=nodes,
output_names=["u", "v", "w", "p"],
export_map={"U": ["u", "v", "w"], "p": ["p"]},
mask_fn = mask_fn,
requires_grad=False,
batch_size=1024,
)
ic_domain.add_inferencer(voxel_inferencer, "vox_inf")
window_domain.add_constraint(voxel_inferencer, "voxel_inferencer")
slv = SequentialSolver(
cfg,
[(1, ic_domain), (nr_time_windows, window_domain)],
custom_update_operation=time_window_net.move_window,
)
# start flow solver
slv.solve()
if name == “main”:
run()
and the error I get is:
####################################
could not unroll graph!
This is probably because you are asking to compute a value that is not an output of any node
####################################
invar: [x, y, z]
requested var: [u, v, w, p]
computable var: [x, y, z, continuity]
####################################
Nodes in graph:
node: Sympy Node: continuity
evaluate: SympyToTorch
inputs:
derivatives: [u__x, v__y, w__z]
outputs: [continuity]
optimize: False
node: Sympy Node: momentum_x
evaluate: SympyToTorch
inputs: [u, v, w]
derivatives: [p__x, u__t, u__x, u__x__x, u__y, u__y__y, u__z, u__z__z]
outputs: [momentum_x]
optimize: False
node: Sympy Node: momentum_y
evaluate: SympyToTorch
inputs: [u, v, w]
derivatives: [p__y, v__t, v__x, v__x__x, v__y, v__y__y, v__z, v__z__z]
outputs: [momentum_y]
optimize: False
node: Sympy Node: momentum_z
evaluate: SympyToTorch
inputs: [u, v, w]
derivatives: [p__z, w__t, w__x, w__x__x, w__y, w__y__y, w__z, w__z__z]
outputs: [momentum_z]
optimize: False
node: Sympy Node: normal_dot_vel
evaluate: SympyToTorch
inputs: [normal_x, normal_y, normal_z, u, v, w]
derivatives:
outputs: [normal_dot_vel]
optimize: False
node: Arch Node: time_window_network
evaluate: MovingTimeWindowArch
inputs: [x, y, z, t]
derivatives:
outputs: [u, v, w, p, u_prev_step, v_prev_step, w_prev_step, p_prev_step, u_prev_step_diff, v_prev_step_diff, w_prev_step_diff, p_prev_step_diff]
optimize: True
####################################
Error executing job with overrides:
Traceback (most recent call last):
File “examples/transient_aneurysm/transient_aneurysm.py”, line 315, in run
voxel_inferencer = VoxelInferencer(
File “/opt/conda/lib/python3.8/site-packages/modulus-22.9-py3.8.egg/modulus/domain/inferencer/voxel.py”, line 81, in init
super().init(
File “/opt/conda/lib/python3.8/site-packages/modulus-22.9-py3.8.egg/modulus/domain/inferencer/vtkpointwise.py”, line 96, in init
super().init(
File “/opt/conda/lib/python3.8/site-packages/modulus-22.9-py3.8.egg/modulus/domain/inferencer/pointwise.py”, line 66, in init
self.model = Graph(
File “/opt/conda/lib/python3.8/site-packages/modulus-22.9-py3.8.egg/modulus/graph.py”, line 94, in init
raise RuntimeError(“Failed Unrolling Graph”)
RuntimeError: Failed Unrolling Graph