Airflow can not through the diffuser

I simulated the air flow in a room through the diffuser, but it’s seems doesn’t work well. The air flow stuck above the diffuser and doesn’t affect in the room.
I created three different zones and controlled their batch sizes, as shown in the picture below with the inlet flow coming from the top.


Does anyone know what’s this problem?

here is my code

#params
    nu=0.01
    rho=1.0
    inlet_vel=2.63

    #geometry
    geometries = Build_Geometry()
    geo_wall :Geometry = geometries.wall
    geo_interior :Geometry = geometries.interior
    geo_s_interior_1 :Geometry = geometries.s_interior_1
    geo_s_interior_2 :Geometry = geometries.s_interior_2
    


    geo_inlet_1:Geometry = geometries.inlet_1
    geo_inlet_2:Geometry = geometries.inlet_2
    geo_outlet:Geometry = geometries.outlet
    geo_diffuser_1 = geometries.diffuser_1
    geo_diffuser_2 = geometries.diffuser_2
    x, y = Symbol("x"), Symbol("y")
    # make list of nodes to unroll graph on
    ze = ZeroEquation(nu=nu, rho=rho, dim=2,max_distance=(4.2) / 2)
    ns = NavierStokes(nu=ze.equations["nu"], rho=1.0, dim=2, time=False)
    normal_dot_vel = NormalDotVec(["u", "v"])
    flow_net = instantiate_arch(
        input_keys=[Key("x"), Key("y")],
        output_keys=[Key("u"), Key("v"), Key("p")],
        cfg=cfg.arch.fully_connected,
    )
    nodes = (
        ns.make_nodes()
        + ze.make_nodes()
        + normal_dot_vel.make_nodes()
        + [flow_net.make_node(name="flow_network")]
    )

    # make domain
    domain = Domain()
    # inlet
   
    inlet_1 = PointwiseBoundaryConstraint(
        nodes=nodes,
        geometry=geo_inlet_1,
        outvar={"u": 0, "v": inlet_vel},
        batch_size=cfg.batch_size.inlet,

    )
    domain.add_constraint(inlet_1, "inlet_1")

    inlet_2 = PointwiseBoundaryConstraint(
        nodes=nodes,
        geometry=geo_inlet_2,
        outvar={"u": 0, "v": inlet_vel},
        batch_size=cfg.batch_size.inlet,
    )
    domain.add_constraint(inlet_2, "inlet_2")
    # outlet
    outlet = PointwiseBoundaryConstraint(
        nodes=nodes,
        geometry=geo_outlet,
        outvar={"p": 0},
        batch_size=cfg.batch_size.outlet,
    )
    domain.add_constraint(outlet, "outlet")
    #diffuser
    diffuser_1 = PointwiseBoundaryConstraint(
        nodes=nodes,
        geometry=geo_diffuser_1,
        outvar={"u": 0, "v": 0},
        batch_size=cfg.batch_size.diffuser,
    )
    domain.add_constraint(diffuser_1, "diffuser_1")

    diffuser_2 = PointwiseBoundaryConstraint(
        nodes=nodes,
        geometry=geo_diffuser_2,
        outvar={"u": 0, "v": 0},
        batch_size=cfg.batch_size.diffuser,
    )
    domain.add_constraint(diffuser_2, "diffuser_2")

    #wall
    
    wall = PointwiseBoundaryConstraint(
        nodes=nodes,
        geometry=geo_wall,
        outvar={"u": 0, "v": 0},
        batch_size=cfg.batch_size.wall,
        criteria=y < 3.5098,
    )
    domain.add_constraint(wall, "wall")
    # interior flow
   
    interior_flow = PointwiseInteriorConstraint(
        nodes=nodes,
        geometry=geo_wall-geo_s_interior_1-geo_s_interior_2,
        outvar={"continuity": 0, "momentum_x": 0, "momentum_y": 0},
        batch_size=cfg.batch_size.interior_flow,
        compute_sdf_derivatives=True,
        lambda_weighting={
            "continuity": Symbol("sdf"),
            "momentum_x": Symbol("sdf"),
            "momentum_y": Symbol("sdf"),
        },
    )
    domain.add_constraint(interior_flow, "interior_flow")

    s_interior_flow_1 = PointwiseInteriorConstraint(
        nodes=nodes,
        geometry=geo_s_interior_1 - geo_diffuser_1,
        outvar={"continuity": 0, "momentum_x": 0, "momentum_y": 0},
        batch_size=cfg.batch_size.s_interior_flow,
        compute_sdf_derivatives=True,
        lambda_weighting={
            "continuity": Symbol("sdf"),
            "momentum_x": Symbol("sdf"),
            "momentum_y": Symbol("sdf"),
        },
    )
    domain.add_constraint(s_interior_flow_1, "s_interior_flow_1")

    s_interior_flow_2 = PointwiseInteriorConstraint(
        nodes=nodes,
        geometry=geo_s_interior_2 - geo_diffuser_2,
        outvar={"continuity": 0, "momentum_x": 0, "momentum_y": 0},
        batch_size=cfg.batch_size.s_interior_flow,
        compute_sdf_derivatives=True,
        lambda_weighting={
            "continuity": Symbol("sdf"),
            "momentum_x": Symbol("sdf"),
            "momentum_y": Symbol("sdf"),
        },
    )
    domain.add_constraint(s_interior_flow_2, "s_interior_flow_2")

    # add inferencer data
    #{x: (0.0, 4.2), y: (0.0, 3.5098)}  
    no_slip = geo_wall - geo_diffuser_1 -geo_diffuser_2
    vtk_obj = VTKUniformGrid(
        bounds=[(0.0, 4.2),(0.0, 3.509)],
        npoints=[1024, 1024],
        export_map={"u": ["u", "v"], "p": ["p"]},
    )

    def mask_fn(x, y):
        sdf = no_slip.sdf({"x": x, "y": y}, {})
        return sdf["sdf"] < 0

    grid_inference = PointVTKInferencer(
        vtk_obj=vtk_obj,
        nodes=nodes,
        input_vtk_map={"x": "x", "y": "y"},
        output_names=["u", "v", "p"],
        mask_fn=mask_fn,
        mask_value=np.nan,
        requires_grad=False,
        batch_size=100000,
    )
    domain.add_inferencer(grid_inference, "grid_inference")

    # make solver
    slv = Solver(cfg, domain)

    # start solver
    slv.solve()

room_2d.zip (4.2 KB)

Hello,

I would be interested to know if by any chance you have already found a solution or at least have a clue as to what could be causing this problem, as I think I have a similar problem.

In your case, I would look at the SDF. If you are composing a geometry from several individual geometries, I am not sure if the calculated SDF values are actually correct. So it could be that you have an SDF value of 0 at the boundary where the inlet regions meet the interior. And I can imagine that this can lead to problems with the SDF based lambda_weighting.

Thanks Daniel !
You are right. I removed calculating SDF in each interior and the air can now go through the diffuser, but I am struggling to converge this case. After 200k-300k steps, the airflow is still incorrect when going through the diffuser.

Hi,
as I mentioned in my first post, I have a similar problem with my test case, where the flow field forms well in and around the inlet area and seems physically correct, but does not form in the area of interest. And as I said, I haven’t found the cause or a workable solution for this. So if you have found a suitable modification to your case that drastically improves the results, I would be very happy if you could share it.

Here are two thoughts that may help you:

    # normalize geometries
    def normalize_geo(geo, center, scale):
        geo = geo.translate([-c for c in center])
        geo = geo.scale(scale)
        return geo

    def get_geo_center(geo):
        bounds = geo.bounds.bound_ranges

        center = []
        for key in bounds.keys():
            center.append((bounds[key][0] + bounds[key][1]) / 2)

        return tuple(center)

    center_orig = get_geo_center(geo.channel_outer)
    geo.inlet = normalize_geo(geo.inlet, center_orig, geometry_scale)
    geo.outlet = normalize_geo(geo.outlet, center_orig, geometry_scale)
    #  ..... and so on
  • The diffuser might lead to sharp gradients. So it might be beneficial to try another net architecture like FourierNetArch instead of the fully connected neural network. Architectures In Modulus Sym - NVIDIA Docs