Repository: Genesis-Embodied-AI/Genesis
File: genesis/engine/couplers/ipc_coupler/coupler.py (Python)

Code before:

        # Pre-compute the entity set for rigid state retrieval
        self._rigid_retrieve_entity_set = set(
            self._entities_by_coupling_type["two_way_soft_constraint"]
            + self._entities_by_coupling_type["ipc_only"]
            + self._articulation_with_non_fixed_base
        )

        # Pre-allocate coupling data for the exact number of ABD bodies matching the entity set
        n_coupling_items = sum(
            entity_idx in self._rigid_retrieve_entity_set for _, _, entity_idx in self._abd_body_idx_to_link.values()
        )
        self.coupling_data = IPCCouplingData(n_coupling_items)

    def _init_ipc(self):
        """Initialize IPC system components"""

        # Derive IPC logging level from Genesis logger
        if gs.logger.level > logging.DEBUG:
            UIPCLogger.set_level(UIPCLogger.Level.Error)
            UIPCTimer.disable_all()

        # Create workspace directory for IPC output, named after scene UID.
        # The UID contains < and > which are illegal in Windows paths.
        uid_safe = re.sub(r"[<>]", "", str(self.sim.scene.uid))
        workspace = os.path.join(tempfile.gettempdir(), f"genesis_ipc_{uid_safe}")
        os.makedirs(workspace, exist_ok=True)

        # Note: gpu_device option may need to be set via CUDA environment variables (CUDA_VISIBLE_DEVICES)
        # before Genesis initialization, as libuipc Engine does not expose device selection in constructor
        self._ipc_engine = Engine("cuda", workspace)
        self._ipc_world = World(self._ipc_engine)

        # Create IPC scene with configuration
        config = build_ipc_scene_config(self.options, self.sim.options)
        self._ipc_scene = Scene(config)

        # Create constitutions
        self._ipc_abd = AffineBodyConstitution()
        self._ipc_stk = StableNeoHookean()
        self._ipc_nks = StrainLimitingBaraffWitkinShell()  # For cloth
        self._ipc_dsb = DiscreteShellBending()  # For cloth bending
        self._ipc_eac = ExternalArticulationConstraint()
        # Add constitutions to scene
        self._ipc_scene.constitution_tabular().insert(self._ipc_abd)
        self._ipc_scene.constitution_tabular().insert(self._ipc_stk)
        self._ipc_scene.constitution_tabular().insert(self._ipc_eac)

        # Set up contact model (physical parameters)
        self._ipc_scene.contact_tabular().default_model(
            self.options.contact_friction_mu, self.options.contact_resistance

Review comment (suggestion):
Just do ` workspace = os.path.join(tempfile.gettempdir(), f"genesis_ipc_{self.sim.scene.uid.full()}")`

Code after:
        # Pre-compute the entity set for rigid state retrieval
        self._rigid_retrieve_entity_set = set(
            self._entities_by_coupling_type["two_way_soft_constraint"]
            + self._entities_by_coupling_type["ipc_only"]
            + self._articulation_with_non_fixed_base
        )

        # Pre-allocate coupling data for the exact number of ABD bodies matching the entity set
        n_coupling_items = sum(
            entity_idx in self._rigid_retrieve_entity_set for _, _, entity_idx in self._abd_body_idx_to_link.values()
        )
        self.coupling_data = IPCCouplingData(n_coupling_items)

    def _init_ipc(self):
        """Initialize IPC system components"""

        # Derive IPC logging level from Genesis logger
        if gs.logger.level > logging.DEBUG:
            UIPCLogger.set_level(UIPCLogger.Level.Error)
            UIPCTimer.disable_all()

        # Create workspace directory for IPC output, named after scene UID.
        workspace = os.path.join(tempfile.gettempdir(), f"genesis_ipc_{self.sim.scene.uid.full()}")
        os.makedirs(workspace, exist_ok=True)

        # Note: gpu_device option may need to be set via CUDA environment variables (CUDA_VISIBLE_DEVICES)
        # before Genesis initialization, as libuipc Engine does not expose device selection in constructor
        self._ipc_engine = Engine("cuda", workspace)
        self._ipc_world = World(self._ipc_engine)

        # Create IPC scene with configuration
        config = build_ipc_scene_config(self.options, self.sim.options)
        self._ipc_scene = Scene(config)

        # Create constitutions
        self._ipc_abd = AffineBodyConstitution()
        self._ipc_stk = StableNeoHookean()
        self._ipc_nks = StrainLimitingBaraffWitkinShell()  # For cloth
        self._ipc_dsb = DiscreteShellBending()  # For cloth bending
        self._ipc_eac = ExternalArticulationConstraint()
        # Add constitutions to scene
        self._ipc_scene.constitution_tabular().insert(self._ipc_abd)
        self._ipc_scene.constitution_tabular().insert(self._ipc_stk)
        self._ipc_scene.constitution_tabular().insert(self._ipc_eac)

        # Set up contact model (physical parameters)
        self._ipc_scene.contact_tabular().default_model(
            self.options.contact_friction_mu, self.options.contact_resistance
        )

        # Create separate contact elements for ABD, FEM, Cloth, and Ground to control their interactions