deepmind-research
deepmind-research copied to clipboard
Questions in the dataset of the meshgraphnet
I have some questions about the data structure of the meshgraphnet, especially for CylinderFlow and Airfoil: cells: [num_steps, num_nodes, num_dimensions(3, triangular mesh is combined with three nodes)] mesh-pos: [num_steps, num_nodes, num_dimensions(2)] node_type: [num_steps, num_nodes, num_dimensions(1)] velocity: [num_steps, num_nodes, num_dimensions(2, x-direction velocity and y-direction velocity of each node)] pressure: [num_steps, num_nodes, num_dimensions(1, the pressure of each node)]
I can't make sure my understanding of your dataset is true. So, if my understanding is wrong, please point it out. Thanks.
There are still some questions else existing.
For the node_type: can you explain the node type carefully? such as the meaning of NORMAL, OBSTACLE, AIRFOIL, HANDLE, INFLOW, OUTFLOW, WALL_BOUNDARY and SIZE? The data of the velocity and pressure is the node's velocity and pressure, not the grid's, is it? Looking forward to your reply. Thanks.
I can't make sure my understanding of your dataset is true
Thanks for your message, yes, that description seems accurate.
The data of the velocity and pressure is the node's velocity and pressure, not the grid's, is it?
Yes, it is the value of the fields sampled at the node positions.
Thanks for your reply. I've generated the dataset successfully.
I can't make sure my understanding of your dataset is true
Thanks for your message, yes, that description seems accurate.
The data of the velocity and pressure is the node's velocity and pressure, not the grid's, is it?
Yes, it is the value of the fields sampled at the node positions.
That's really helpful.
I can't make sure my understanding of your dataset is true
Thanks for your message, yes, that description seems accurate.
The data of the velocity and pressure is the node's velocity and pressure, not the grid's, is it?
Yes, it is the value of the fields sampled at the node positions.
Hi, Alvaro. Sorry to disturb u. I encountered a problem while adding global variables (such as density, solid concentration, and so on) as an input of the meshgraphnet. I've searched many papers about it, but no relative contents are obtained. Therefore, could u tell any relative information about this problem? I've tried adding global variables to each node. But it doesn't work well.
I've tried adding global variables to each node. But it doesn't work well.
All we do in this paper is to concatenate the global feature to all of the nodes, and that has always worked well enough as it is a very general way to condition a model on a global variable. I am not sure why specifically it may not be working in your case, perhaps the problem is just too hard, or you don't have enough data for each value of the global variable.
I've tried adding global variables to each node. But it doesn't work well.
All we do in this paper is to concatenate the global feature to all of the nodes, and that has always worked well enough as it is a very general way to condition a model on a global variable. I am not sure why specifically it may not be working in your case, perhaps the problem is just too hard, or you don't have enough data for each value of the global variable.
Sorry, I didn’t describe this problem clearly. Ur paper tries to concatenate the feature of each node to its position and connectivity(hope my understanding isn’t wrong). But what about it when considering the ATM and different liquids? For example, gasoline and water have very different physical characteristics (different density, different viscosity and so on). And how can we add these characteristics into your model? I guess the atmosphere is same in ur cases. But how should we do when considering different atmosphere such as 1 ATM, 2 ATM and 2.5 ATM?
Unfortunately I don't know enough about your project to follow your message 100%. This is roughly the approach we woudl follow:
- if nodes are of different types, then first I would just give a one hot type to each node to indicate its type.
- then if nodes of different types have characteristics ranging very different values (for example for one type it takes values between 0.001 and 0.01, and for the other between 10 and 100), then first I would normalize each characteristic to have zero mean unit-variance for each node type, and then concatenate the normalized values
- if the nodes of different types have different characteristics, I would use zero padding values when a given node type does not have that characteristic. In any cases, the model would still be able to use the one-hot type to know when a value is padding.
- then whether the property is global or not is sort of a detail. If a property is global, you just concatenate the property to all of the nodes in the graph, if it is global for a certain node type then concatenate the global value to the nodes of the corresponding types, and if it is different for each node, then just concatenate a different value for each node.
If this approach does not work, however, I am not sure I have any more advice to offer unfortunately, as it seems it would be something very specific about your problem.
Many thanks for ur helpful advice. For ur third advice, does the 'concatenate' mean that the global property is treated as a property of the nodes, same as their position and type? Or a new message-passing method passing the global property to the node?
For ur third advice, does the 'concatenate' mean that the global property is treated as a property of the nodes, same as their position and type? Or a new message-passing method passing the global property to the node?
All features I am referring to from the point of view of the model would be treated just like any other node feature, and then we just let the training figure out how to use then. There would be for sure other more domain specific ways to do it, but this is how we did it in this paper.
All features I am referring to are from the point of view of the model would be treated just like any other node feature, and then just let the training figure out how to use it. There are for sure other ways to do it, but this is how we did it in this paper.
I see. Thanks for ur help. Ur replies are really helpful for my project.
Hi, Alvaro. Sorry to disturb you again. I've just found an interesting paper name 'MultiScale MeshGraphNets', extending from the meshraphnets. However, I'm still confused about some details of it. So is there any possibility to share the code with me for a better understanding?
Thanks for reaching, I am not sure if there is a plan to open source the code of MultiScale MeshGraphNets, I would recommend to contact the corresponding authors directly.
Thanks for your help. I've contacted him with email.
Hello, I seem to have a similar question related to this topic. I am trying to make the deforming plate dataset work. I implemented the graph net and it learns the other datasets with no problem, I also used my own particle based data and it also works fine. However, in the case of the deforming plate, the node input features are problematic. Based on the paper and the answers here, I prepare the input this way: node_features = normalize_by_column(concatenate((prescribed_motion, node type), dim=1)) Where the prescribed motion is the next step world velocity, as in the paper. Then to emulate zero padding for the simulated nodes I add: node_fetures[body_indices, :motion_dimension] = 0.0 With this, the zero vector that is the prescriben motion of the fixed indices will be non zero after normalziation and the actual zero vector of the (nonexistent) prescribed motion of the body nodes will be zero padding. Using this, the network predicts the in-contact nodes sticking to the intruder and the surrounding nodes stretching like jello. Is my input preparation wrong? Reading the paper, this is the method I concluded with. Thank you for your relpy.
Thanks for your message:
For DeformingPlate assuming you have:
current_position
: position at t
future_position
: position at t+1
node_type
: node types.
we used something like:
prescribed_motion = where(node_type==KINEMATIC_TYPE, future_position - current_position, 0.)
node_features = concat([current_position, prescribed_motion, node_type_one_hot])
@sebestyenja Hi, I am also trying to use the model with my own data. Did you created a tfrecord to give in input to the model? Or do you used "from_generator" methods? Thanks!
I am using both methods. With the dataset from the paper and with my own datasets as well.
Thanks for the answer! Did you eventually manage to implement deforming_plate code? I am also trying but I'm having some issues on how to implement the informations about the edge radius for the world_edges (to compute external dynamics in case of collisions)... My goal is to train the model with my datasets that comes from a simple structural case (a simple beam that is bending) and to use this model with my own data
Yes I did with multiple datasets. The world edges are built based on proximity.
Hi @alvarosg ,
I think I have a following question related with this thread. As paper mentioned about cylinder flow, it could directly predict the pressure without any input information of pressure if I understand correctly. But I think the pressure value could go several ranges for different type of nodes, like you mentioned here in first scenario. I am wondering how you guys manage this in the input dataset pipeline since I did not see additional node features except velocity and node type.
Thanks in advance, This is fantastic work!
Best, ZY
Hi ZY,
pressure
is contained in the CylinderFlow dataset, we just don't do anything with it in this demonstration code. But if you want to play around with it, you can do so easily by modifying run_model.py
:57. E.g. ds = dataset.add_targets(ds, ['velocity', 'pressure'], add_history=False)
will add the fields pressure
and target|pressure
into the inputs dictionary.
Then you can add another target to the model prediction, i.e. use output_size=3 instead of 2 in EncodeProcessDecode
and output_normalizer
, add a second loss in cfd_model:loss etc.
Hope this helps, Tobias
Hi @tobiaspfaff ,
Thanks for your help. So, if I understand correctly, pressure has to be in the both input and output so that the output from decoder is the change of pressure like velocity? Or just simply next-step pressure?
Also, in your last sentence, do you suggest adding one more additional loss for pressure, like velocity, then combine them together?
Well that depends on the system you're modeling-- for incompressible Navier-Stokes like CylinderFlow, pressure isn't a state variable, i.e. you don't need to know p_t to predict v_t+1, p_t+1. So I wouldn't feed it into the network as an input; this is different for compressible flow. You can check A.1 in the MGN paper for which quantities we used as input and output. For similar reasons we directly predicted p, not dp/dt - so there wouldn't be an integration step as there is for velocity. There's of course different ways you can do this, one thing you sometimes see in papers is normalizing pressure (see citation [40] in the paper) which makes it a bit easier to predict. But direct prediction worked reasonably well for us.
To your second question, yes, we simply added the losses for velocity and pressure. Because our loss is in normalized space the different scales of the predicted quantities aren't generally an issue (unless their distribution is very far from Gaussian).
Hi @tobiaspfaff ,
Thanks so much for your explanation. I agree with your first part of response for incompressible NS equations, and this is what I think about how to manage it properly. However, for my own case which is different even though it is still under incompressible region, the pressure may go several oder of magnitude for different nodes in simulation for each time step (really bad scale even I do it with zero-mean, unit variance), do you think it is possible to use L1 norm for pressure to stabilize the prediction?
Yes, this is probably just something you need to try. Just note that with a L1 loss you might need to be a bit more careful with balancing the two losses. You could also look at e.g. predicting log(p) or sqrt(p) instead of p (before normalization), if that improves your data distribution-- we did this for the stress in DeformingPlate, which also had a very large range of values. Good luck!
Yes, this is probably just something you need to try. Just note that with a L1 loss you might need to be a bit more careful with balancing the two losses. You could also look at e.g. predicting log(p) or sqrt(p) instead of p (before normalization), if that improves your data distribution-- we did this for the stress in DeformingPlate, which also had a very large range of values. Good luck!
Thank you so much for your help! @tobiaspfaff . I am so much appreciated.
Sorry for bothering you again, I just have one more question regrading tf.Graph in TF2. I have rebuilt MGN in TF2 and sonnet 2 successfully in notebook environment to test partial of cylinder_flow dataset in order to fit the memory footprint there. However, once I rearrange it to OOP typed Python scripts (like the code developed here) and test on hpc, it always complains about retracting, especially the training loop (l use tf.function to decorate single batch update and call it in the training loop like tf.train.MonitoredTrainSeesion in the run_model.py
). I am curious do you have some general suggestion to avoid this happen? Because I have tried all the official TF tutorials about using tf.function, but all of them are dealing with much easier cases than here.
Thanks for you reply, ZY
I am still confused to generate the tfrecord data files, can anyone provide any advice? Thanks very much!