Skip to content

adding graph timeseries#807

Open
ndem0 wants to merge 6 commits into
0.3from
0.3-ts-graph
Open

adding graph timeseries#807
ndem0 wants to merge 6 commits into
0.3from
0.3-ts-graph

Conversation

@ndem0

@ndem0 ndem0 commented Jun 11, 2026

Copy link
Copy Markdown
Member

Description

Added the graph time series condition.

Checklist

  • Code follows the project’s Code Style Guidelines
  • Tests have been added or updated
  • Documentation has been updated if necessary
  • Pull request is linked to an open issue

@ndem0 ndem0 requested review from a team and dario-coscia as code owners June 11, 2026 15:40

@dario-coscia dario-coscia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comment on an extra feature, but overall looks great. Be aware that tests are failing

residuals = []

# Iterate over the time steps
for step in range(1, batch["input"].shape[2]):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@GiovanniCanali what do you think to add the pushforward trick here as well? Is it a condition thing or solver thing? Having it is very easy (we just need the no grad option)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a condition-level concern, since gradient computation must be enabled or disabled when evaluating the residual between the model prediction and the target. As you noted, the implementation should be straightforward. Since the forward method is inherited from TimeSeriesCondition, we should consider implementing it directly there.

@GiovanniCanali GiovanniCanali added enhancement New feature or request pr-to-fix Label for PR that needs modification 0.3 Related to 0.3 release labels Jun 18, 2026

@GiovanniCanali GiovanniCanali left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is still a work in progress, but I have added a few comments below.

@ndem0, please remember to add the appropriate mapping to the Condition factory so that the software automatically dispatches graph time-series conditions and standard time-series conditions to the correct classes.


return _DataManager(input=graph)

def evaluate(self, batch, solver):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method appears to be identical to the one defined in TimeSeriesCondition and should therefore be inherited without modification.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now some small differences in accessing the node data, I would keep it otherwise several if are needed in the TimeSerieCondition

return torch.stack(residuals).as_subclass(torch.Tensor)

@property
def input(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method appears to be identical to the one defined in TimeSeriesCondition and should therefore be inherited without modification.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

residuals = []

# Iterate over the time steps
for step in range(1, batch["input"].shape[2]):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is definitely a condition-level concern, since gradient computation must be enabled or disabled when evaluating the residual between the model prediction and the target. As you noted, the implementation should be straightforward. Since the forward method is inherited from TimeSeriesCondition, we should consider implementing it directly there.

@ndem0 ndem0 linked an issue Jun 18, 2026 that may be closed by this pull request
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

badge

Code Coverage Summary

Filename                                                                       Stmts    Miss  Cover    Missing
---------------------------------------------------------------------------  -------  ------  -------  ----------------------------------------------------------------------------------------------
__init__.py                                                                       12       3  75.00%   28-37
graph.py                                                                           2       0  100.00%
label_tensor.py                                                                    2       0  100.00%
operator.py                                                                        2       0  100.00%
trainer.py                                                                         2       0  100.00%
type_checker.py                                                                    2       0  100.00%
utils.py                                                                           2       0  100.00%
_src/__init__.py                                                                   0       0  100.00%
_src/adaptive_function/__init__.py                                                 0       0  100.00%
_src/adaptive_function/adaptive_celu.py                                            6       0  100.00%
_src/adaptive_function/adaptive_elu.py                                             6       0  100.00%
_src/adaptive_function/adaptive_exp.py                                             6       0  100.00%
_src/adaptive_function/adaptive_function_interface.py                             13       0  100.00%
_src/adaptive_function/adaptive_gelu.py                                            6       0  100.00%
_src/adaptive_function/adaptive_mish.py                                            6       0  100.00%
_src/adaptive_function/adaptive_relu.py                                            6       0  100.00%
_src/adaptive_function/adaptive_sigmoid.py                                         6       0  100.00%
_src/adaptive_function/adaptive_silu.py                                            6       0  100.00%
_src/adaptive_function/adaptive_siren.py                                           6       0  100.00%
_src/adaptive_function/adaptive_softmax.py                                         6       0  100.00%
_src/adaptive_function/adaptive_softmin.py                                         6       0  100.00%
_src/adaptive_function/adaptive_tanh.py                                            6       0  100.00%
_src/adaptive_function/base_adaptive_function.py                                  43       2  95.35%   142, 146
_src/callback/__init__.py                                                          0       0  100.00%
_src/callback/optim/__init__.py                                                    0       0  100.00%
_src/callback/optim/switch_optimizer.py                                           20       0  100.00%
_src/callback/optim/switch_scheduler.py                                           20       0  100.00%
_src/callback/processing/__init__.py                                               0       0  100.00%
_src/callback/processing/data_normalizer.py                                       61       0  100.00%
_src/callback/processing/metric_tracker.py                                        29       1  96.55%   96
_src/callback/processing/pina_progress_bar.py                                     26       1  96.15%   105
_src/callback/refinement/__init__.py                                               0       0  100.00%
_src/callback/refinement/base_refinement.py                                       41       3  92.68%   71, 78, 96
_src/callback/refinement/r3_refinement.py                                         25       0  100.00%
_src/callback/refinement/refinement_interface.py                                  14       0  100.00%
_src/condition/__init__.py                                                         0       0  100.00%
_src/condition/base_condition.py                                                  43       4  90.70%   102-103, 116, 142
_src/condition/condition.py                                                       18       3  83.33%   143, 159-164
_src/condition/condition_interface.py                                             26       0  100.00%
_src/condition/data_condition.py                                                  34       0  100.00%
_src/condition/domain_equation_condition.py                                       31       1  96.77%   44
_src/condition/graph_time_series_condition.py                                     44       2  95.45%   76, 117
_src/condition/input_equation_condition.py                                        31       0  100.00%
_src/condition/input_target_condition.py                                          29       0  100.00%
_src/condition/time_series_condition.py                                           63       1  98.41%   207
_src/core/__init__.py                                                              0       0  100.00%
_src/core/graph.py                                                               113      16  85.84%   99-100, 112, 124, 126, 142, 144, 163-169, 182, 271
_src/core/label_tensor.py                                                        251      26  89.64%   81, 121, 148, 165, 177, 182, 188-193, 273, 280, 332, 348, 490, 537, 629, 664-673, 684-689, 710
_src/core/operator.py                                                             72       2  97.22%   268, 464
_src/core/trainer.py                                                              75       7  90.67%   154-161, 165-172, 180-188, 311
_src/core/type_checker.py                                                         22       0  100.00%
_src/core/utils.py                                                                73       5  93.15%   141, 178, 181, 184, 268
_src/data/__init__.py                                                              0       0  100.00%
_src/data/aggregator.py                                                           21       1  95.24%   53
_src/data/condition_subset.py                                                     26       3  88.46%   91-99
_src/data/creator.py                                                              57       8  85.96%   118, 224-238
_src/data/data_module.py                                                          55       5  90.91%   91-92, 96-97, 179
_src/data/single_batch_data_loader.py                                             25       0  100.00%
_src/data/manager/batch_manager.py                                                15       2  86.67%   44-45
_src/data/manager/data_manager.py                                                 12       1  91.67%   39
_src/data/manager/data_manager_interface.py                                       11       0  100.00%
_src/data/manager/graph_data_manager.py                                           79       4  94.94%   75, 165, 185, 207
_src/data/manager/tensor_data_manager.py                                          34       2  94.12%   82, 108
_src/domain/__init__.py                                                            0       0  100.00%
_src/domain/base_domain.py                                                        68       0  100.00%
_src/domain/base_operation.py                                                     45       4  91.11%   63, 106, 129, 139
_src/domain/cartesian_domain.py                                                   54       1  98.15%   68
_src/domain/difference.py                                                         27       0  100.00%
_src/domain/domain_interface.py                                                   25       0  100.00%
_src/domain/ellipsoid_domain.py                                                   81       4  95.06%   98, 108-109, 253
_src/domain/exclusion.py                                                          35       1  97.14%   107
_src/domain/intersection.py                                                       34       1  97.06%   97
_src/domain/operation_interface.py                                                 9       0  100.00%
_src/domain/simplex_domain.py                                                     83       5  93.98%   212, 226, 237, 249, 288
_src/domain/union.py                                                              24       0  100.00%
_src/equation/__init__.py                                                          0       0  100.00%
_src/equation/base_equation.py                                                    14       1  92.86%   52
_src/equation/equation.py                                                         16       1  93.75%   62
_src/equation/equation_interface.py                                                6       0  100.00%
_src/equation/system_equation.py                                                  23       0  100.00%
_src/equation/zoo/__init__.py                                                      0       0  100.00%
_src/equation/zoo/acoustic_wave_equation.py                                       14       0  100.00%
_src/equation/zoo/advection_equation.py                                           30       0  100.00%
_src/equation/zoo/allen_cahn_equation.py                                          16       0  100.00%
_src/equation/zoo/burgers_equation.py                                             24       0  100.00%
_src/equation/zoo/diffusion_reaction_equation.py                                  17       0  100.00%
_src/equation/zoo/fixed_flux.py                                                   13       0  100.00%
_src/equation/zoo/fixed_gradient.py                                               13       0  100.00%
_src/equation/zoo/fixed_laplacian.py                                              18       2  88.89%   63-68
_src/equation/zoo/fixed_value.py                                                  12       0  100.00%
_src/equation/zoo/helmholtz_equation.py                                           14       0  100.00%
_src/equation/zoo/poisson_equation.py                                             12       0  100.00%
_src/loss/__init__.py                                                              0       0  100.00%
_src/loss/base_dual_loss.py                                                       10       0  100.00%
_src/loss/dual_loss_interface.py                                                   7       0  100.00%
_src/loss/lp_loss.py                                                              19       0  100.00%
_src/loss/power_loss.py                                                           15       0  100.00%
_src/model/__init__.py                                                             0       0  100.00%
_src/model/average_neural_operator.py                                             31       2  93.55%   73, 82
_src/model/deeponet.py                                                            85      13  84.71%   179-182, 201, 232, 271, 281, 291, 301, 311, 321, 476, 486
_src/model/equivariant_graph_neural_operator.py                                   51       1  98.04%   219
_src/model/feed_forward.py                                                        89      11  87.64%   58, 195, 200, 278-292
_src/model/fourier_neural_operator.py                                             78      10  87.18%   100-104, 114, 159-163, 222, 224, 246, 346
_src/model/graph_neural_operator.py                                               40       2  95.00%   58, 60
_src/model/kernel_neural_operator.py                                              34       6  82.35%   83-84, 103-104, 123-124
_src/model/kolmogorov_arnold_network.py                                           14       0  100.00%
_src/model/low_rank_neural_operator.py                                            27       2  92.59%   89, 98
_src/model/multi_feed_forward.py                                                  12       5  58.33%   25-31
_src/model/pirate_network.py                                                      28       1  96.43%   119
_src/model/sindy.py                                                               21       0  100.00%
_src/model/spline.py                                                             124       5  95.97%   133, 156, 164, 236, 475
_src/model/spline_surface.py                                                      68      12  82.35%   151-152, 187-190, 200, 213-218, 258
_src/model/vectorized_spline.py                                                  153      15  90.20%   208, 311, 317, 347-348, 408, 410, 446, 448, 450, 529, 542, 615, 630, 647
_src/model/block/__init__.py                                                       0       0  100.00%
_src/model/block/average_neural_operator_block.py                                 12       0  100.00%
_src/model/block/convolution.py                                                   64      13  79.69%   77, 81, 85, 91, 97, 111, 114, 151, 161, 171, 181, 191, 201
_src/model/block/convolution_2d.py                                               146      27  81.51%   155, 162, 282, 314, 379-433, 456
_src/model/block/embedding.py                                                     48       7  85.42%   93, 143-146, 155, 168
_src/model/block/fourier_block.py                                                 31       0  100.00%
_src/model/block/gno_block.py                                                     22       4  81.82%   73-77, 87
_src/model/block/integral.py                                                      18       4  77.78%   22-25, 71
_src/model/block/kan_block.py                                                     43       0  100.00%
_src/model/block/low_rank_block.py                                                24       0  100.00%
_src/model/block/orthogonal.py                                                    37       0  100.00%
_src/model/block/pirate_network_block.py                                          25       1  96.00%   89
_src/model/block/pod_block.py                                                     75      10  86.67%   56-59, 71, 84, 114, 151-156, 191, 216
_src/model/block/rbf_block.py                                                    179      25  86.03%   18, 42, 53, 64, 75, 86, 97, 223, 280, 282, 298, 301, 329, 335, 363, 367, 511-524
_src/model/block/residual.py                                                      46       0  100.00%
_src/model/block/spectral.py                                                      83       4  95.18%   132, 140, 262, 270
_src/model/block/stride.py                                                        28       7  75.00%   55, 58, 61, 67, 72-74
_src/model/block/utils_convolution.py                                             22       3  86.36%   58-60
_src/model/block/message_passing/__init__.py                                       0       0  100.00%
_src/model/block/message_passing/deep_tensor_network_block.py                     21       0  100.00%
_src/model/block/message_passing/en_equivariant_network_block.py                  47       1  97.87%   164
_src/model/block/message_passing/equivariant_graph_neural_operator_block.py       36       0  100.00%
_src/model/block/message_passing/interaction_network_block.py                     23       0  100.00%
_src/model/block/message_passing/radial_field_network_block.py                    20       0  100.00%
_src/optim/__init__.py                                                             0       0  100.00%
_src/optim/optimizer_interface.py                                                  7       0  100.00%
_src/optim/scheduler_interface.py                                                  7       0  100.00%
_src/optim/torch_optimizer.py                                                     14       0  100.00%
_src/optim/torch_scheduler.py                                                     16       0  100.00%
_src/problem/__init__.py                                                           0       0  100.00%
_src/problem/base_problem.py                                                      86       7  91.86%   52-53, 65-72
_src/problem/inverse_problem.py                                                   23       0  100.00%
_src/problem/parametric_problem.py                                                 9       0  100.00%
_src/problem/problem_interface.py                                                 25       0  100.00%
_src/problem/spatial_problem.py                                                    9       0  100.00%
_src/problem/time_dependent_problem.py                                             9       0  100.00%
_src/problem/zoo/__init__.py                                                       0       0  100.00%
_src/problem/zoo/acoustic_wave_problem.py                                         33       2  93.94%   25-26
_src/problem/zoo/advection_problem.py                                             25       1  96.00%   22
_src/problem/zoo/allen_cahn_problem.py                                            25       0  100.00%
_src/problem/zoo/burgers_problem.py                                               23       1  95.65%   23
_src/problem/zoo/diffusion_reaction_problem.py                                    35       3  91.43%   25-33
_src/problem/zoo/helmholtz_problem.py                                             30       0  100.00%
_src/problem/zoo/inverse_poisson_problem.py                                       52       3  94.23%   48-54
_src/problem/zoo/poisson_problem.py                                               17       0  100.00%
_src/problem/zoo/supervised_problem.py                                            11       0  100.00%
_src/solver/autoregressive_ensemble_solver.py                                      8       0  100.00%
_src/solver/autoregressive_single_model_solver.py                                  8       0  100.00%
_src/solver/base_solver.py                                                       113       4  96.46%   200, 207, 331, 388
_src/solver/causal_physics_informed_single_model_solver.py                        68       5  92.65%   140, 159, 218, 295, 320
_src/solver/competitive_physics_informed_solver.py                                59       0  100.00%
_src/solver/ensemble_solver.py                                                    10       0  100.00%
_src/solver/gradient_physics_informed_single_model_solver.py                      11       0  100.00%
_src/solver/multi_model_solver.py                                                 10       0  100.00%
_src/solver/physics_informed_ensemble_solver.py                                    9       0  100.00%
_src/solver/physics_informed_single_model_solver.py                                9       0  100.00%
_src/solver/rba_physics_informed_single_model_solver.py                           11       0  100.00%
_src/solver/self_adaptive_physics_informed_solver.py                              72       1  98.61%   126
_src/solver/single_model_solver.py                                                 8       0  100.00%
_src/solver/solver_interface.py                                                   21       0  100.00%
_src/solver/supervised_ensemble_solver.py                                          6       0  100.00%
_src/solver/supervised_single_model_solver.py                                      6       0  100.00%
_src/solver/mixin/autoregressive_mixin.py                                         50      11  78.00%   159-186
_src/solver/mixin/condition_aggregator_mixin.py                                   11       0  100.00%
_src/solver/mixin/ensemble_mixin.py                                                5       0  100.00%
_src/solver/mixin/gradient_enhanced_mixin.py                                      39       2  94.87%   67, 76
_src/solver/mixin/manual_optimization_mixin.py                                    16       0  100.00%
_src/solver/mixin/multi_model_mixin.py                                            24       1  95.83%   27
_src/solver/mixin/physics_informed_mixin.py                                        8       0  100.00%
_src/solver/mixin/residual_based_attention_mixin.py                               53       1  98.11%   89
_src/solver/mixin/single_model_mixin.py                                           19       0  100.00%
_src/weighting/__init__.py                                                         0       0  100.00%
_src/weighting/base_weighting.py                                                  28       1  96.43%   49
_src/weighting/linear_weighting.py                                                16       0  100.00%
_src/weighting/no_weighting.py                                                     4       0  100.00%
_src/weighting/ntk_weighting.py                                                   18       0  100.00%
_src/weighting/scalar_weighting.py                                                13       0  100.00%
_src/weighting/self_adaptive_weighting.py                                         12       0  100.00%
_src/weighting/weighting_interface.py                                             11       0  100.00%
adaptive_function/__init__.py                                                     15       0  100.00%
callback/__init__.py                                                              15       3  80.00%   37-46
condition/__init__.py                                                             10       0  100.00%
data/__init__.py                                                                  12       3  75.00%   24-33
data/manager.py                                                                    6       0  100.00%
domain/__init__.py                                                                11       0  100.00%
equation/__init__.py                                                              13       4  69.23%   44-54
equation/zoo.py                                                                   12       0  100.00%
loss/__init__.py                                                                  13       4  69.23%   29-39
model/__init__.py                                                                 16       0  100.00%
model/block/__init__.py                                                           14       0  100.00%
model/block/message_passing.py                                                     6       0  100.00%
optim/__init__.py                                                                 11       3  72.73%   25-34
problem/__init__.py                                                               13       3  76.92%   26-35
problem/zoo.py                                                                    10       0  100.00%
solver/__init__.py                                                                27       6  77.78%   95-109
solver/mixin.py                                                                   10      10  0.00%    3-29
weighting/__init__.py                                                              8       0  100.00%
TOTAL                                                                           5765     393  93.18%

Results for commit: 12680c2

Minimum allowed coverage is 80.123%

♻️ This comment has been updated with latest results

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

0.3 Related to 0.3 release enhancement New feature or request pr-to-fix Label for PR that needs modification

Projects

None yet

Development

Successfully merging this pull request may close these issues.

TimeSeries condition for graph data

3 participants