Hi everyone,
I am working on creating a forward solution model for a simple flow inside a pipe (3D channel) using Navier-Stokes library available in Modulus-Sym. The medium is Glycerin, and the details of the channel and fluid properties are as follows:
Channel and Fluid Details:
- Channel length = 3 m
- Channel radius = 0.1 m
- Fluid density = 1260 kg/m3
- Fluid kinematic viscosity = 0.00119 m2/s.
- Inlet velocity = 0.06 m/s
Issues/Queries:
-
Inlet Constraint Issue: When I checked the inlet constraint in the VTP file, the velocity at the inlet is not correctly applied. Instead of the expected 0.06 m/s, it shows a much lower value of 0.004 m/s.
What could be causing this discrepancy?
-
Unrealistic Flow and Pressure Distribution
After inferencing, the results show unrealistic flow and pressure distributions, even though the training losses are low.
Below is a figure comparing the results of Modulus and OpenFOAM
Flow velocity is mostly uniform.
Please help me understand why need to consider and missed in trained the model.
Code used to train model.
import os
import numpy as np
from sympy import Symbol, Eq
from stl import mesh # Ensure numpy-stl is installed
import torch
import modulus.sym
from modulus.sym.hydra import to_absolute_path, instantiate_arch, ModulusConfig
from modulus.sym.solver import Solver
from modulus.sym.domain import Domain
from modulus.sym.geometry.primitives_3d import Box
from modulus.sym.geometry.primitives_2d import Rectangle
from modulus.sym.domain.constraint import PointwiseBoundaryConstraint, PointwiseInteriorConstraint
from modulus.sym.domain.inferencer import PointwiseInferencer
from modulus.sym.domain.monitor import PointwiseMonitor
from modulus.sym.key import Key
from modulus.sym.eq.pdes.navier_stokes import NavierStokes
from modulus.sym.utils.io import InferencerPlotter
from modulus.sym.geometry.primitives_3d import Cylinder
from modulus.sym.utils.io.vtk import var_to_polyvtk
from sympy import sqrt, Max, Abs
@modulus.sym.main(config_path="conf", config_name="config")
def run(cfg: ModulusConfig) -> None:
# Fluid : Glycerin properties
nu = 0.00119 # kinematic viscosity (m^2/s)
rho = 1260 # density (kg/m^3)
ns = NavierStokes(nu=nu, rho=rho, dim=3, time=False)
# Define the geometry of the pipe
length = 3 # Length of the pipe (m)
radius = 0.1 # Radius of the pipe (m)
inlet_vel = 0.06 # Maximum velocity at the center
# Instantiate the neural network architecture
flow_net = instantiate_arch(
input_keys=[Key("x"), Key("y"), Key("z")],
output_keys=[Key("u"), Key("v"), Key("w"), Key("p")],
cfg=cfg.arch.fully_connected,
)
nodes = (
ns.make_nodes()
+ [flow_net.make_node(name="flow_network")]
)
x, y, z = Symbol("x"), Symbol("y"), Symbol("z")
pipe = Cylinder(
center=(0, 0, 0),
radius=radius,
height=length,
)
# sample geometry for plotting in Paraview
nr_points = 100000 # number of points to sample
s = pipe.sample_boundary(nr_points=nr_points)
var_to_polyvtk(s, "boundaryChecking")
# Create simulation domain
domain = Domain()
# Inlet boundary condition
inlet_bc = PointwiseBoundaryConstraint(
nodes=nodes,
geometry=pipe,
outvar={"u": 0, "v": 0, "w":inlet_vel }, # Pass the velocity components
batch_size=cfg.batch_size.Inlet,
lambda_weighting={"u": 1.0 - 20 * Abs(x), "v": 1.0 - 20 * Abs(y), "w":1}, # weight edges to be zero
criteria=Eq(Symbol("z"), -1.5), # Apply at the inlet (z = -1.5)
)
domain.add_constraint(inlet_bc, "inlet")
# Outlet boundary condition (zero pressure)
outlet_bc = PointwiseBoundaryConstraint(
nodes=nodes,
geometry=pipe,
outvar={"p": 0},
batch_size=cfg.batch_size.Outlet,
criteria=Eq(Symbol("z"), 1.5), # Outlet at z = 1.5
lambda_weighting={"p":1}, # weight edges to be zero
)
domain.add_constraint(outlet_bc, "outlet")
# No-slip condition on the pipe walls
no_slip_bc = PointwiseBoundaryConstraint(
nodes=nodes,
geometry=pipe,
outvar={"u": 0, "v": 0, "w": 0},
batch_size=cfg.batch_size.Wall,
lambda_weighting={"u":1, "v":1, "w":1}, # weight edges to be zero
# criteria=Abs(Symbol("x")**2 + Symbol("y")**2 - radius**2) < 1e-6, # Updated criteria
criteria=Eq((Symbol("x")**2 + Symbol("y")**2) - radius**2, 0), # Updated criteria
)
domain.add_constraint(no_slip_bc, "no_slip")
# Interior constraints for Navier-Stokes equations
interior = PointwiseInteriorConstraint(
nodes=nodes,
geometry=pipe,
outvar={"continuity": 0, "momentum_x": 0, "momentum_y": 0, "momentum_z": 0},
batch_size=cfg.batch_size.Interior,
lambda_weighting={
"continuity": Symbol("sdf"),
"momentum_x": Symbol("sdf"),
"momentum_y": Symbol("sdf"),
"momentum_z": Symbol("sdf"),
},
)
domain.add_constraint(interior, "interior")
# Create the solver
slv = Solver(cfg, domain)
# Solve the problem
slv.solve()
if __name__ == "__main__":
run()