Skip to content

refactor: simplify data module and condition layer - #837

Merged
ndem0 merged 4 commits into
devfrom
data_module_simplification
Nov 6, 2026
Merged

ndem0 merged 4 commits into
devfrom
data_module_simplification

Conversation

@ndem0

@ndem0 ndem0 commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Description

Remove data managers (Tensor/Graph/Batch), aggregator, condition subset, creator and single-batch loader. Conditions now store data directly in tensor/graph variants and materialize into id-based batches; graph tensor fields are attached per-graph so batching concatenates node-wise. Trainer drops automatic_batching in favour of per-condition dataloader_cls and collate_fn resolution. Adapt DataNormalizer and R3Refinement callbacks and rewrite tests for the new API.

This PR fixes #833

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

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

There are confirmed runtime-breaking issues in the new condition/data path (notably graph input equation evaluation and slice indexing for graph conditions) that must be fixed before merging.

Review effort: Lite
Findings: 2 Medium severity

Open (2)
What changed in this PR

This PR refactors PINA’s data pipeline by removing the legacy data-manager/creator/aggregator stack and shifting batching/materialization responsibilities into condition implementations, with DataModule now operating on per-condition sample-id tensors and materializing condition batches on-device.

Changes:

  • Replaced _Aggregator + _Creator with Batcher + MultiLoader, and rewired DataModule to split per-condition id tensors and call condition.materialize(...) during device transfer.
  • Introduced TensorCondition / GraphCondition base classes to unify data storage + batching for tensor and graph conditions; updated condition variants to use these.
  • Updated Trainer API to drop automatic_batching and add per-condition dataloader_cls / collate_fn resolution; adapted callbacks and tests accordingly.
File Description
tests/​test_trainer.py Updates Trainer constructor tests and adds coverage for per-condition dataloader/collate option validation & warnings.
tests/​test_data/​test_tensor_data_manager.py Removes tests for deleted tensor data manager abstraction.
tests/​test_data/​test_single_batch_data_loader.py Removes tests for deleted single-batch loader.
tests/​test_data/​test_loader.py Replaces _Aggregator tests with MultiLoader tests.
tests/​test_data/​test_graph_data_manager.py Removes tests for deleted graph data manager abstraction.
tests/​test_data/​test_data_module.py Updates DataModule tests to assert id-tensor subsets instead of _ConditionSubset.
tests/​test_data/​test_creator.py Removes tests for deleted dataloader creator.
tests/​test_data/​test_condition_subset.py Removes tests for deleted condition subset wrapper.
tests/​test_condition/​test_time_series_condition.py Updates tests to use materialize and new tensor-backed condition storage.
tests/​test_condition/​test_input_target_condition.py Updates tests for dict-based batches and materialize semantics across tensor/graph variants.
tests/​test_condition/​test_input_equation_condition.py Updates tests to use materialize for tensor/graph inputs.
tests/​test_condition/​test_graph_time_series_condition.py Updates tests for GraphTimeSeriesCondition and materialize behavior.
tests/​test_condition/​test_data_condition.py Updates tests for dict-based batches and conditional variables under new materialization.
tests/​test_callback/​test_data_normalizer.py Aligns DataNormalizer tests with condition-owned data storage.
pina/​data/​manager.py Removes top-level exports for deleted data manager layer.
pina/​data/​__init__.py Exposes new Batcher/MultiLoader APIs and removes old internal exports.
pina/​condition/​__init__.py Updates public condition exports to include new graph/tensor condition base types.
pina/​_src/​data/​single_batch_data_loader.py Deletes single-batch loader implementation.
pina/​_src/​data/​manager/​tensor_data_manager.py Deletes tensor data manager implementation.
pina/​_src/​data/​manager/​graph_data_manager.py Deletes graph data manager implementation.
pina/​_src/​data/​manager/​data_manager.py Deletes data manager factory.
pina/​_src/​data/​manager/​data_manager_interface.py Deletes data manager interface.
pina/​_src/​data/​manager/​batch_manager.py Deletes legacy batch container.
pina/​_src/​data/​loader.py Adds MultiLoader to aggregate per-condition dataloaders.
pina/​_src/​data/​data_module.py Refactors DataModule to id-based subsets + on-device condition.materialize batching.
pina/​_src/​data/​creator.py Deletes old multi-condition dataloader creator.
pina/​_src/​data/​condition_subset.py Deletes old subset wrapper used for cyclic indexing/auto-batching.
pina/​_src/​data/​batcher.py Adds Batcher to construct per-condition dataloaders over id tensors.
pina/​_src/​data/​aggregator.py Deletes old _Aggregator implementation.
pina/​_src/​core/​trainer.py Drops automatic_batching, adds per-condition dataloader/collate option resolution, and passes into DataModule.
pina/​_src/​condition/​time_series_condition.py Refactors time-series condition to tensor-backed storage with shared unroll helper.
pina/​_src/​condition/​tensor_condition.py Introduces tensor-backed storage/materialization implementation for conditions.
pina/​_src/​condition/​input_target_condition.py Switches to tensor/graph condition variants and dict-based batches.
pina/​_src/​condition/​input_equation_condition.py Switches to tensor/graph condition variants and shared evaluation path.
pina/​_src/​condition/​graph_time_series_condition.py Refactors graph time-series condition to graph-backed storage/materialization.
pina/​_src/​condition/​graph_condition.py Introduces graph-backed storage/materialization implementation for conditions.
pina/​_src/​condition/​domain_equation_condition.py Clarifies non-materializable semantics for domain-sampled conditions.
pina/​_src/​condition/​data_condition.py Switches to tensor/graph condition variants and updates semantics/docs.
pina/​_src/​condition/​condition_interface.py Updates condition contract to center on materialize(...).
pina/​_src/​condition/​base_condition.py Removes legacy dataloader/collate mechanisms from the base class and adds _unwrap_single.
pina/​_src/​callback/​refinement/​r3_refinement.py Avoids autograd graph retention by detaching selected refinement points.
pina/​_src/​callback/​refinement/​base_refinement.py Updates refinement bookkeeping for id-tensor datasets.
pina/​_src/​callback/​processing/​data_normalizer.py Refactors normalizer to operate on condition-held data rather than dataset wrappers.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread pina/_src/condition/graph_condition.py Resolved
@GiovanniCanali
GiovanniCanali changed the base branch from master to dev October 1, 2026 11:33

@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.

Great job, @ndem0! This significantly simplifies the logic connecting conditions and batching. However, there are still a few points that require attention:

  1. The documentation does not currently reflect the changes introduced in the source code. Please update it accordingly.
  2. Is the Condition factory class affected in any way by the proposed changes? Please verify that its behavior remains consistent.
  3. Tests for Batcher are currently missing.
  4. Each condition currently follows a common structure, with a base class that is then specialized into Tensor and Graph implementations. TimeSeriesCondition, however, does not follow this pattern, as it develops two independent classes. Would it be possible to introduce a common base class with corresponding specializations, consistently with the other condition classes?
  5. The materialize method appears to be identical in both TensorCondition and GraphCondition. Consider moving this implementation to BaseCondition to avoid duplication.

Comment thread pina/_src/data/loader.py Resolved
Comment thread pina/_src/core/trainer.py Resolved
@GiovanniCanali GiovanniCanali added enhancement New feature or request pr-to-fix Label for PR that needs modification labels Oct 1, 2026

@dario-coscia dario-coscia left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @ndem0 ! I have checked the src files only and left some comments. I did not check the tests, I will do once the PR is ready for review and not draft anymore.

Anyway, I like the approach as it also more readable and reduces the number of lines of code!

Comment thread pina/_src/condition/base_condition.py Resolved
Comment thread pina/_src/condition/base_condition.py Resolved
Comment thread pina/_src/condition/graph_condition.py Resolved
Comment thread pina/_src/condition/graph_condition.py Resolved
@ndem0
ndem0 marked this pull request as ready for review November 3, 2026 11:20
@ndem0
ndem0 requested a review from a team as a code owner November 3, 2026 11:20
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

badge

Code Coverage Summary

Filename                                                                       Stmts    Miss  Cover    Missing
---------------------------------------------------------------------------  -------  ------  -------  ------------------------------------------------------------------------------------------
__init__.py                                                                       20       4  80.00%   43-54
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                                       79       4  94.94%   115, 160, 213, 215
_src/callback/processing/metric_tracker.py                                        29       1  96.55%   102
_src/callback/processing/pina_progress_bar.py                                     26       1  96.15%   111
_src/callback/refinement/__init__.py                                               0       0  100.00%
_src/callback/refinement/base_refinement.py                                       49       3  93.88%   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                                                  15       2  86.67%   20, 42
_src/condition/condition.py                                                       16       3  81.25%   39, 46-49
_src/condition/condition_interface.py                                             18       0  100.00%
_src/condition/domain_equation_condition.py                                       37       4  89.19%   58, 89-91
_src/condition/graph_condition.py                                                 27       3  88.89%   20-22
_src/condition/graph_input_equation_condition.py                                  16       0  100.00%
_src/condition/graph_input_target_condition.py                                     7       0  100.00%
_src/condition/graph_time_series_condition.py                                     39       1  97.44%   140
_src/condition/input_equation_condition.py                                        24       0  100.00%
_src/condition/input_target_condition.py                                          23       1  95.65%   39
_src/condition/tensor_condition.py                                                30       2  93.33%   36-37
_src/condition/time_series_condition.py                                           72       1  98.61%   261
_src/core/__init__.py                                                              0       0  100.00%
_src/core/data_module.py                                                          74       1  98.65%   209
_src/core/graph.py                                                               122      21  82.79%   110-111, 123, 135, 137, 153, 155, 174-180, 193, 328, 494-506
_src/core/label_tensor.py                                                        284      23  91.90%   81, 148, 165, 177, 182, 188-193, 277, 285, 310, 312, 356, 372, 542, 589, 687, 722-731, 768
_src/core/operator.py                                                             72       2  97.22%   268, 503
_src/core/trainer.py                                                              82       5  93.90%   120-126, 201-209, 293
_src/core/type_checker.py                                                         22       0  100.00%
_src/core/utils.py                                                                73       5  93.15%   158, 201, 204, 207, 304
_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%   54
_src/equation/equation.py                                                         16       1  93.75%   72
_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%   77-82
_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/loss/sinkhorn_loss.py                                                        28       0  100.00%
_src/model/__init__.py                                                             0       0  100.00%
_src/model/average_neural_operator.py                                             31       2  93.55%   86, 95
_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%   228
_src/model/feed_forward.py                                                        89      11  87.64%   68, 215, 220, 298-312
_src/model/fourier_neural_operator.py                                             78      10  87.18%   112-116, 126, 171-175, 234, 236, 258, 371
_src/model/graph_neural_operator.py                                               40       2  95.00%   70, 72
_src/model/kernel_neural_operator.py                                              34       6  82.35%   99-100, 119-120, 139-140
_src/model/kolmogorov_arnold_network.py                                           14       0  100.00%
_src/model/low_rank_neural_operator.py                                            27       2  92.59%   103, 112
_src/model/multi_feed_forward.py                                                  12       5  58.33%   36-42
_src/model/pirate_network.py                                                      28       1  96.43%   129
_src/model/sindy.py                                                               21       0  100.00%
_src/model/spline.py                                                             124       6  95.16%   133, 156, 164, 236, 450, 475
_src/model/spline_surface.py                                                      68      12  82.35%   159-160, 195-198, 208, 221-226, 266
_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%   95, 99, 103, 109, 115, 129, 132, 177, 187, 197, 207, 217, 227
_src/model/block/convolution_2d.py                                               146      27  81.51%   177, 184, 304, 336, 401-455, 478
_src/model/block/embedding.py                                                     48       7  85.42%   103, 153-156, 165, 178
_src/model/block/fourier_block.py                                                 31       0  100.00%
_src/model/block/gno_block.py                                                     22       4  81.82%   83-87, 97
_src/model/block/integral.py                                                      18       4  77.78%   31-34, 80
_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%   98
_src/model/block/pod_block.py                                                     75      10  86.67%   65-68, 80, 93, 123, 160-165, 200, 225
_src/model/block/rbf_block.py                                                    179      25  86.03%   18, 42, 53, 64, 75, 86, 97, 234, 291, 293, 309, 312, 340, 346, 374, 378, 522-535
_src/model/block/residual.py                                                      46       0  100.00%
_src/model/block/spectral.py                                                      83       4  95.18%   152, 160, 292, 300
_src/model/block/stride.py                                                        28       7  75.00%   66, 69, 72, 78, 83-85
_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%   174
_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                                                      93      10  89.25%   54-55, 67-74, 234-239
_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%   27-28
_src/problem/zoo/advection_problem.py                                             25       1  96.00%   24
_src/problem/zoo/allen_cahn_problem.py                                            25       0  100.00%
_src/problem/zoo/burgers_problem.py                                               23       1  95.65%   25
_src/problem/zoo/diffusion_reaction_problem.py                                    35       3  91.43%   27-35
_src/problem/zoo/helmholtz_problem.py                                             30       0  100.00%
_src/problem/zoo/inverse_poisson_problem.py                                       53       3  94.34%   51-57
_src/problem/zoo/poisson_problem.py                                               17       0  100.00%
_src/problem/zoo/supervised_problem.py                                            17       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                                                       126       5  96.03%   200, 207, 373, 394, 439
_src/solver/causal_physics_informed_single_model_solver.py                        70       5  92.86%   149, 168, 230, 315, 340
_src/solver/competitive_physics_informed_solver.py                                61       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                              74       1  98.65%   135
_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                                          7       0  100.00%
_src/solver/supervised_single_model_solver.py                                      7       0  100.00%
_src/solver/mixin/autoregressive_mixin.py                                         50      11  78.00%   159-186
_src/solver/mixin/condition_aggregator_mixin.py                                   13       0  100.00%
_src/solver/mixin/ensemble_mixin.py                                               19       0  100.00%
_src/solver/mixin/gradient_enhanced_mixin.py                                      34       2  94.12%   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                               46       0  100.00%
_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                                                             19       5  73.68%   47-58
data/__init__.py                                                                   9       9  0.00%    3-25
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                                                                  14       4  71.43%   31-41
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                                                                           5660     394  93.04%

Results for commit: d9623f5

Minimum allowed coverage is 80.123%

♻️ This comment has been updated with latest results

@ndem0 ndem0 added pr-to-review Label for PR that are ready to been reviewed and removed pr-to-fix Label for PR that needs modification labels Nov 3, 2026
@ndem0
ndem0 force-pushed the data_module_simplification branch from d1601c3 to bed8c9f Compare November 3, 2026 12:18

@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.

Thank you @ndem0, this PR considerably simplifies the logic governing conditions and batch management.

There are four main points I would like to address before approval:

  • The previous implementation supported InputEquationCondition with Graph input, but the support appears to have been lost. Can we restore it, or is there a specific reason it is no longer supported?
  • Several docstrings do not meet our documentation standards. I’ve left comments highlighting where changes are needed.
  • I like the idea of grouping .rst files by module to make the API landing page cleaner. However, the current _code.rst structure is confusing. Please see the comment below.
  • Please restore conf.py to use PINA’s documentation extension. If required dependencies are missing, add them to pyproject.toml rather than switching to local resources.

Comment thread pina/_src/equation/base_equation.py Resolved
Comment thread pina/_src/equation/equation.py Resolved
Comment thread pina/_src/equation/equation.py Resolved
Comment thread pina/_src/equation/system_equation.py Resolved
Comment thread pina/_src/loss/__init__.py Resolved
Comment thread pina/_src/core/data_module.py Resolved
Comment thread pina/_src/core/data_module.py Resolved
Comment thread pina/_src/solver/base_solver.py Resolved
@ndem0

ndem0 commented Nov 5, 2026

Copy link
Copy Markdown
Member Author
  • The previous implementation supported InputEquationCondition with Graph input, but the support appears to have been lost. Can we restore it, or is there a specific reason it is no longer supported?

@GiovanniCanali Totally not! Many issues were also because of that: several classes were managing more than one implementation internally, making the structure overcomplicated and quite impossibile to debug/check. How about batching in this mixed condition tensor/graph? We have to support new method again, the user is probably unaware about the real class he's using, and I do not see any advantage. The real difference is in the problem statement.
InputTargetCondition(...)
vs
{Graph,Tensor}InputTargetCondition

@GiovanniCanali

Copy link
Copy Markdown
Collaborator
  • The previous implementation supported InputEquationCondition with Graph input, but the support appears to have been lost. Can we restore it, or is there a specific reason it is no longer supported?

@GiovanniCanali Totally not! Many issues were also because of that: several classes were managing more than one implementation internally, making the structure overcomplicated and quite impossibile to debug/check. How about batching in this mixed condition tensor/graph? We have to support new method again, the user is probably unaware about the real class he's using, and I do not see any advantage. The real difference is in the problem statement. InputTargetCondition(...) vs {Graph,Tensor}InputTargetCondition

I totally agree with you, and I probably did not explain myself well: correct me if I am wrong, but the current implementation is lacking GraphInputEquationCondition. Is this simply because it has not been implemented yet, or is there any blocking issue?

@ndem0

ndem0 commented Nov 5, 2026

Copy link
Copy Markdown
Member Author

@GiovanniCanali

Copy link
Copy Markdown
Collaborator

Already in this PR with the unittest https://github.com/PINA-org/PINA/blob/04423ff2e04834a347c0c9f8250a34f9706f95a3/pina/_src/condition/graph_input_target_condition.py

No, this is GraphInputTargetCondition. I am asking for GraphInputEquationCondition.

@ndem0

ndem0 commented Nov 5, 2026

Copy link
Copy Markdown
Member Author

Yeah right, no not implemented yet. Ill add so we can merge.

@GiovanniCanali

Copy link
Copy Markdown
Collaborator

Ready to merge @ndem0! Consider squashing some commits. Also, the first two commits are very similar.

@dario-coscia

Copy link
Copy Markdown
Member

Looks great for me as well! We cut many lines (and a lot of glue code!). Thanks Nico 🚀

ndem0 added 3 commits November 6, 2026 09:57
Remove data managers (Tensor/Graph/Batch), aggregator, condition subset,
creator and single-batch loader. Conditions now store data directly in
tensor/graph variants and materialize into id-based batches; graph tensor
fields are attached per-graph so batching concatenates node-wise. Trainer
drops automatic_batching in favour of per-condition dataloader_cls and
collate_fn resolution. Adapt DataNormalizer and R3Refinement callbacks and
rewrite tests for the new API.
Delegate subgraph creation to Graph.create_subgraph (k-hop,
LabelTensor-label-preserving). Add GraphInputTargetCondition as a public
supervised graph condition. Update SupervisedProblem to detect
Graph/Data input and wrap it automatically.
BaseWeighting.aggregate merges per-condition weight updates to support
one-condition-per-step batching. DataNormalizer and BaseRefinement/
R3Refinement updated to use train_dataset tensor and batch-dict API.
Trainer warns when num_workers/pin_memory are set with batch_size=None.
All tests updated to the new condition and DataModule interface.
@ndem0
ndem0 force-pushed the data_module_simplification branch from 36baee0 to f0c1e6b Compare November 6, 2026 08:59
Add repo root to sys.path so Sphinx uses local source. Remove stale RST
files for deleted data classes. Create per-module index.rst files with
hidden toctrees matching the pina.* hierarchy for a collapsible sidebar.
Remove automodule directives from class pages to fix right-column TOC.
Clean the src directory, remove unnecessary code and file.

Co-authored-by: Giovanni Canali <GiovanniCanali@users.noreply.github.com>
@ndem0
ndem0 force-pushed the data_module_simplification branch from f0c1e6b to d9623f5 Compare November 6, 2026 09:10
@ndem0
ndem0 merged commit aba591d into dev Nov 6, 2026
18 checks passed
@GiovanniCanali
GiovanniCanali deleted the data_module_simplification branch November 6, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request pr-to-review Label for PR that are ready to been reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants