How to Create a Cutout on a 3D Object Surface

Question:
I am planning to simulate airflow in a simple box-shaped space (5m x 7m x 3m) with a supply vent located on the ceiling. The room is represented as a 3D box, and I need to create a cutout (3m x 1m) on the top surface to model the supply vent. My goal is to ensure that the boundary points for the room and the supply vent do not overlap, allowing the application of distinct boundary conditions to each surface.

I have tried two approaches to achieve this, but both present different challenges:

Approach 1:

  • Process: Create the room using a 3D box primitive and define the supply cutout using a 2D surface. Subtract the 2D supply cutout from the 3D box.
  • Issue: The subtraction operation itself works without errors. However, exporting the boundary points of the resulting room object after the operation results in errors. (Code and error details are provided below.)
import numpy as np
import pyvista as pv
from modulus.sym.geometry.primitives_2d import Rectangle
from modulus.sym.geometry.primitives_3d import Box
from modulus.sym.utils.io.vtk import var_to_polyvtk
#Create room from 3D box primitive
Room = Box((0,0,0),(5,7,3)) 
#Approach 1
Supplyplane = Rectangle( (1.5, 1), (4.5,2) )
Room_v1 = Room - Supplyplane

#Export
boundary_points1 = Room.sample_boundary(nr_points=100000)
var_to_polyvtk(boundary_points1, "componentvtp/Room_boundary.vtk")

boundary_points2 = Supplyplane.sample_boundary(nr_points=100000)
var_to_polyvtk(boundary_points2, "componentvtp/Supplyplane_boundary.vtk")

boundary_points3 = Room_v1.sample_boundary(nr_points=100000)
var_to_polyvtk(boundary_points3, "componentvtp/Room_v1_boundary.vtk")


#############################################################################
############################ ERROR ##########################################
#############################################################################

---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
Cell In[6], line 8
      5 boundary_points2 = Supplyplane.sample_boundary(nr_points=100000)
      6 var_to_polyvtk(boundary_points2, "componentvtp/Supplyplane_boundary.vtk")
----> 8 boundary_points3 = Room_v1.sample_boundary(nr_points=100000)
      9 var_to_polyvtk(boundary_points3, "componentvtp/Room_v1_boundary.vtk")

File ~/.local/lib/python3.8/site-packages/modulus/sym/geometry/geometry.py:488, in Geometry.sample_boundary(self, nr_points, criteria, parameterization, quasirandom)
    484 closed_boundary_criteria = _boundary_criteria(criteria)
    486 # compute required points on each curve
    487 curve_areas = np.array(
--> 488     [
    489         curve.approx_area(parameterization, criteria=closed_boundary_criteria)
    490         for curve in self.curves
    491     ]
    492 )
    493 assert np.sum(curve_areas) > 0, "Geometry has no surface"
    494 curve_probabilities = curve_areas / np.linalg.norm(curve_areas, ord=1)

File ~/.local/lib/python3.8/site-packages/modulus/sym/geometry/geometry.py:489, in <listcomp>(.0)
    484 closed_boundary_criteria = _boundary_criteria(criteria)
    486 # compute required points on each curve
    487 curve_areas = np.array(
    488     [
...
    401 sdf_normal_plus = self.sdf(
    402     invar_normal_plus, params, compute_sdf_derivatives=False
    403 )["sdf"]

KeyError: 'z'
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

Approach 2:

  • Process: Model both the room and the supply cutout as 3D box primitives, and subtract the 3D cutout box from the room box.
  • Outcome: Both the subtraction operation and the export of the boundary points work without errors. However, the cutout is not correctly reflected when I inspect the boundary points of the updated room object.

Code used for approach 2 is below.

import numpy as np
import pyvista as pv
from modulus.sym.geometry.primitives_2d import Rectangle
from modulus.sym.geometry.primitives_3d import Box
from modulus.sym.utils.io.vtk import var_to_polyvtk

#Create room from 3D box primitive
Room = Box((0,0,0),(5,7,3)) 

#Approach 2 
Supplybox = Box( (1.5,1,2.99), (4.5,2,3.5))
Room_v2 = Room - Supplybox

#sample boundary 
boundary_points1 = Room.sample_boundary(nr_points=100000)
var_to_polyvtk(boundary_points1, "componentvtp/Room_boundary.vtk")

boundary_points2 = Supplybox.sample_boundary(nr_points=100000)
var_to_polyvtk(boundary_points2, "componentvtp/Supplybox_boundary.vtk")

boundary_points3 = Room_v2.sample_boundary(nr_points=100000)
var_to_polyvtk(boundary_points3, "componentvtp/Room_v2_boundary.vtk")

Attachments:

Fig1. Schematic of room geometry need to be designed for airflow simulation.
Fig2. Comparison of top view highlighting that cutout is not getting created with Approch 2.

I would appreciate any guidance on:

  • Why the issues occur in each approach.
  • Recommendations for creating a cutout on the 3D object surface.

Thank you in advance!

The reason approach 2 does not work becomes clear if you increase the overlap between the boxes.
For example with: Supplybox = Box( (1.5, 1, 1.5), (4.5, 2, 3.5))
You basically subtracted a volume from a volume and then sampled the surface.

I would suggest that you define a “criteria” when creating the boundary conditions.
This would look something like this:

def supply_criteria(invar, params):
    sdf_supplybox = Supplybox.sdf(invar, params)
    return np.less(sdf_supplybox["sdf"], 0)

room_wall = PointwiseBoundaryConstraint(
    nodes=nodes,
    geometry=Room,
    outvar={"u": 0, "v": 0, "w": 0},
    criteria=supply_criteria,
    batch_size=cfg.batch_size.room_wall,
)
domain.add_constraint(room_wall, "room_wall")

In this way, only the points on the walls of the room that are outside the Supplybox are sampled.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.