Unroll graph error in Pointwisemonitor of 2D flow over airfoil with inlet velocity as parameter

Hi, I am using modulus 22.09 to train a model that provide flow field prediction for a 2D airfoil with changing angle of attack and inlet velocity.
However, I encountered a unroll graph error on the pointwisemonitor part, here is the error log:

[19:05:28] - JitManager: {'_enabled': False, '_arch_mode': <JitArchMode.ONLY_ACTIVATION: 1>, '_use_nvfuser': True, '_autograd_nodes': False}
[19:05:28] - GraphManager: {'_func_arch': True, '_debug': False, '_func_arch_allow_partial_hessian': True}
[19:08:11] - Arch Node: flow_network has been converted to a FuncArch node.
[19:13:42] - Arch Node: flow_network has been converted to a FuncArch node.
integral continuity NOT implemented.
[19:14:09] - Arch Node: flow_network has been converted to a FuncArch node.
####################################
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, sdf, area, aoa, x_pos]
requested var: [continuity, momentum_x, momentum_y]
computable var: [x, y, sdf, area, aoa, x_pos, continuity]
####################################
Nodes in graph: 
node: Sympy Node: continuity
evaluate: SympyToTorch
inputs: []
derivatives: [u__x, v__y]
outputs: [continuity]
optimize: False
node: Sympy Node: momentum_x
evaluate: SympyToTorch
inputs: [u, v]
derivatives: [p__x, u__x, u__x__x, u__y, u__y__y]
outputs: [momentum_x]
optimize: False
node: Sympy Node: momentum_y
evaluate: SympyToTorch
inputs: [u, v]
derivatives: [p__y, v__x, v__x__x, v__y, v__y__y]
outputs: [momentum_y]
optimize: False
node: Sympy Node: normal_dot_vel
evaluate: SympyToTorch
inputs: [normal_x, normal_y, u, v]
derivatives: []
outputs: [normal_dot_vel]
optimize: False
node: Arch Node: flow_network
evaluate: FullyConnectedArch
inputs: [x, y, aoa, vel_in]
derivatives: []
outputs: [u, v, p]
optimize: True
####################################

Here is how I set the flow nodes:

    # parametric variation
    vel_in = Symbol("vel_in")
    vel_in_range = (0.0,10.0)
    vel_param = {vel_in:vel_in_range}

    inlet_vel = (vel_in,0.0)
    nonslip_vel = (0.0,0.0)
    outlet_p = 0.0
    volumetric_flow = 20.0*vel_in # this one for integral continuity

    # physical quantities
    kinematic_viscosity = 0.01
    ref_length = 1.
    Re = inlet_vel[0]*ref_length/kinematic_viscosity
    inv_Re = 1./Re
    rho = 1.0


    # make navier stokes equations
    if cfg.custom.turbulent:
        ze = ZeroEquation(nu=0.002, dim=2, time=False, max_distance=0.5)
        ns = NavierStokes(nu=ze.equations["nu"], rho=1.0, dim=2, time=False)
        navier_stokes_nodes = ns.make_nodes() + ze.make_nodes()
    else:
        ns = NavierStokes(nu=0.01, rho=1.0, dim=2, time=False)
        navier_stokes_nodes = ns.make_nodes()
    normal_dot_vel = NormalDotVec(["u", "v"])

    # make network arch
    if cfg.custom.parameterized:
        input_keys = [
            Key("x"),
            Key("y"),
            Key("aoa"),
            Key("vel_in"),
        ]
    else:
        input_keys = [Key("x"), Key("y")]
    flow_net = FullyConnectedArch(
        input_keys=input_keys, output_keys=[Key("u"), Key("v"), Key("p")]
    )

    # make list of nodes to unroll graph on
    flow_nodes = (
        navier_stokes_nodes
        + normal_dot_vel.make_nodes()
        + [flow_net.make_node(name="flow_network")]
    )

Here is the PointwiseMonitor that have the unroll graph error:

    # add monitors
    global_monitor = PointwiseMonitor(
        geo.volume_geo.sample_interior(1000),
        #invar = ["vel_in"],
        output_names=["continuity", "momentum_x", "momentum_y"],
        metrics={
            "mass_imbalance": lambda var: torch.sum(
                var["area"] * torch.abs(var["continuity"])
            ),
            "momentum_imbalance": lambda var: torch.sum(
                var["area"]
                * (torch.abs(var["momentum_x"]) + torch.abs(var["momentum_y"]))
            ),
        },
        nodes=flow_nodes,
        requires_grad=True,
    )
    domain.add_monitor(global_monitor)

Can somebody kindly help me with this unroll graph error?

Best regards.

Hi @TinsenLY

Seems that the graph is not able to get all of the needed inputs for the neural network to predict the velocity components. Is your model able to get access to vel_in in the monitor? I see you have it commented out, is it a parameterized variable in your geometry?

In the error it says:

invar: [x, y, sdf, area, aoa, x_pos]
requested var: [continuity, momentum_x, momentum_y]
computable var: [x, y, sdf, area, aoa, x_pos, continuity]

which tells me that this vel_in variable is potentially missing from the input / cant be computed.

Hi, @ngeneva

Thank you for your reply.

I was trying to add the vel_in using the invar, but it comes out with the error that I have provide mutiple values for the invar. So how should I add the vel_in variable into the monitor? It is not a parameterized variable in geometry, it is parameterized in flow.py.

And then I tried to comment out the monitors and run the code, the loss was large, and the model failed to converge. Does the monitors have influence on the training of the model?

Best regards.

Hi @TinsenLY

I was trying to add the vel_in using the invar , but it comes out with the error that I have provide mutiple values for the invar . So how should I add the vel_in variable into the monitor? It is not a parameterized variable in geometry, it is parameterized in flow.py.

Yes, so in the invar parameter you need to provide a dictionary of numpy arrays that includes vel_in variable as well of the same size. So if your monitor will be using 1000 points, this will need to be an array of 1000 points added to the dictionary produced from the sample_interior method. E.g.:

v = 0.1 #vel in speed
inputs = geo.volume_geo.sample_interior(1000) # Dict of 'x','y','z','area',etc
inputs['vel_in'] = v*np.ones(1000,1) # send this into your monitor

monitor = PointwiseMonitor(
        inputs,
        output_names=["continuity", "momentum_x", "momentum_y"],
      ....
)

The alternative method is to add this variable as a parameterization into the geometry of the system. Basically the geometry model will then serve this variable with the x,y,z coords when building the dataset for the monitor. See the FPGA geometry for an example of this.

And then I tried to comment out the monitors and run the code, the loss was large, and the model failed to converge. Does the monitors have influence on the training of the model?

No something is wrong with your training.