diff --git a/docs/source/_rst/adaptive_function/AdaptiveActivationFunctionInterface.rst b/docs/source/_rst/adaptive_function/AdaptiveActivationFunctionInterface.rst index cf8b6551d..db035b46b 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveActivationFunctionInterface.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveActivationFunctionInterface.rst @@ -3,6 +3,6 @@ AdaptiveActivationFunctionInterface .. currentmodule:: pina.adaptive_function.adaptive_function_interface -.. automodule:: pina.adaptive_function.adaptive_function_interface +.. automodule:: pina._src.adaptive_function.adaptive_function_interface :members: :show-inheritance: diff --git a/docs/source/_rst/adaptive_function/AdaptiveCELU.rst b/docs/source/_rst/adaptive_function/AdaptiveCELU.rst index c4d6d5429..5c04ecde3 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveCELU.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveCELU.rst @@ -1,9 +1,9 @@ AdaptiveCELU ============ -.. currentmodule:: pina.adaptive_function.adaptive_function +.. currentmodule:: pina.adaptive_function -.. autoclass:: AdaptiveCELU +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveCELU :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveELU.rst b/docs/source/_rst/adaptive_function/AdaptiveELU.rst index aab273b08..2b27c4038 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveELU.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveELU.rst @@ -3,7 +3,7 @@ AdaptiveELU .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveELU +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveELU :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveExp.rst b/docs/source/_rst/adaptive_function/AdaptiveExp.rst index a7ee52b20..000f5bab2 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveExp.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveExp.rst @@ -3,7 +3,7 @@ AdaptiveExp .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveExp +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveExp :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveGELU.rst b/docs/source/_rst/adaptive_function/AdaptiveGELU.rst index b4aef14dc..35ae98382 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveGELU.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveGELU.rst @@ -3,7 +3,7 @@ AdaptiveGELU .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveGELU +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveGELU :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveMish.rst b/docs/source/_rst/adaptive_function/AdaptiveMish.rst index d006df054..6b440f5d2 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveMish.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveMish.rst @@ -3,7 +3,7 @@ AdaptiveMish .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveMish +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveMish :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveReLU.rst b/docs/source/_rst/adaptive_function/AdaptiveReLU.rst index d0fe4de68..379ee1d66 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveReLU.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveReLU.rst @@ -3,7 +3,7 @@ AdaptiveReLU .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveReLU +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveReLU :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveSIREN.rst b/docs/source/_rst/adaptive_function/AdaptiveSIREN.rst index 9f132547b..6e4aaf6f0 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveSIREN.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveSIREN.rst @@ -3,7 +3,7 @@ AdaptiveSIREN .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveSIREN +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveSIREN :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveSiLU.rst b/docs/source/_rst/adaptive_function/AdaptiveSiLU.rst index 722678611..b1fa345f1 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveSiLU.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveSiLU.rst @@ -3,7 +3,7 @@ AdaptiveSiLU .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveSiLU +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveSiLU :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveSigmoid.rst b/docs/source/_rst/adaptive_function/AdaptiveSigmoid.rst index 6002ffb31..3a2c19a9b 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveSigmoid.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveSigmoid.rst @@ -3,7 +3,7 @@ AdaptiveSigmoid .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveSigmoid +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveSigmoid :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveSoftmax.rst b/docs/source/_rst/adaptive_function/AdaptiveSoftmax.rst index c2b4c9f09..0a2352508 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveSoftmax.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveSoftmax.rst @@ -3,7 +3,7 @@ AdaptiveSoftmax .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveSoftmax +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveSoftmax :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveSoftmin.rst b/docs/source/_rst/adaptive_function/AdaptiveSoftmin.rst index 5189cb391..d842c5f26 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveSoftmin.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveSoftmin.rst @@ -3,7 +3,7 @@ AdaptiveSoftmin .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveSoftmin +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveSoftmin :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/adaptive_function/AdaptiveTanh.rst b/docs/source/_rst/adaptive_function/AdaptiveTanh.rst index 9a9b380a3..ca183abec 100644 --- a/docs/source/_rst/adaptive_function/AdaptiveTanh.rst +++ b/docs/source/_rst/adaptive_function/AdaptiveTanh.rst @@ -3,7 +3,7 @@ AdaptiveTanh .. currentmodule:: pina.adaptive_function.adaptive_function -.. autoclass:: AdaptiveTanh +.. autoclass:: pina._src.adaptive_function.adaptive_function.AdaptiveTanh :members: :show-inheritance: :inherited-members: AdaptiveActivationFunctionInterface diff --git a/docs/source/_rst/callback/optim/switch_optimizer.rst b/docs/source/_rst/callback/optim/switch_optimizer.rst index 635e79a18..13b7db7ad 100644 --- a/docs/source/_rst/callback/optim/switch_optimizer.rst +++ b/docs/source/_rst/callback/optim/switch_optimizer.rst @@ -2,6 +2,8 @@ Switch Optimizer ===================== .. currentmodule:: pina.callback.optim.switch_optimizer +.. automodule:: pina._src.callback.optim.switch_optimizer + :show-inheritance: .. autoclass:: SwitchOptimizer :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/callback/optim/switch_scheduler.rst b/docs/source/_rst/callback/optim/switch_scheduler.rst index 3176904da..42d5e6be0 100644 --- a/docs/source/_rst/callback/optim/switch_scheduler.rst +++ b/docs/source/_rst/callback/optim/switch_scheduler.rst @@ -2,6 +2,8 @@ Switch Scheduler ===================== .. currentmodule:: pina.callback.optim.switch_scheduler +.. automodule:: pina._src.callback.optim.switch_scheduler + :show-inheritance: .. autoclass:: SwitchScheduler :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/callback/processing/metric_tracker.rst b/docs/source/_rst/callback/processing/metric_tracker.rst index f21cc7730..202522831 100644 --- a/docs/source/_rst/callback/processing/metric_tracker.rst +++ b/docs/source/_rst/callback/processing/metric_tracker.rst @@ -1,7 +1,8 @@ Metric Tracker ================== .. currentmodule:: pina.callback.processing.metric_tracker - +.. automodule:: pina._src.callback.processing.metric_tracker + :show-inheritance: .. autoclass:: MetricTracker :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/callback/processing/normalizer_data_callback.rst b/docs/source/_rst/callback/processing/normalizer_data_callback.rst index a44f0c402..31fd769c8 100644 --- a/docs/source/_rst/callback/processing/normalizer_data_callback.rst +++ b/docs/source/_rst/callback/processing/normalizer_data_callback.rst @@ -2,6 +2,8 @@ Normalizer Data ======================= .. currentmodule:: pina.callback.processing.normalizer_data_callback +.. automodule:: pina._src.callback.processing.normalizer_data_callback + :show-inheritance: .. autoclass:: NormalizerDataCallback :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/callback/processing/pina_progress_bar.rst b/docs/source/_rst/callback/processing/pina_progress_bar.rst index 1d42ad120..da3a878ba 100644 --- a/docs/source/_rst/callback/processing/pina_progress_bar.rst +++ b/docs/source/_rst/callback/processing/pina_progress_bar.rst @@ -1,7 +1,8 @@ PINA Progress Bar ================== .. currentmodule:: pina.callback.processing.pina_progress_bar - +.. automodule:: pina._src.callback.processing.pina_progress_bar + :show-inheritance: .. autoclass:: PINAProgressBar :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/callback/refinement/r3_refinement.rst b/docs/source/_rst/callback/refinement/r3_refinement.rst index eb3bfebf2..5f0da6ea6 100644 --- a/docs/source/_rst/callback/refinement/r3_refinement.rst +++ b/docs/source/_rst/callback/refinement/r3_refinement.rst @@ -1,7 +1,7 @@ Refinments callbacks ======================= -.. currentmodule:: pina.callback.refinement -.. autoclass:: R3Refinement +.. currentmodule:: pina.callback +.. autoclass:: pina._src.callback.refinement.r3_refinement.R3Refinement :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/callback/refinement/refinement_interface.rst b/docs/source/_rst/callback/refinement/refinement_interface.rst index 5e02f2dc3..d1de6429b 100644 --- a/docs/source/_rst/callback/refinement/refinement_interface.rst +++ b/docs/source/_rst/callback/refinement/refinement_interface.rst @@ -1,7 +1,7 @@ Refinement Interface ======================= -.. currentmodule:: pina.callback.refinement -.. autoclass:: RefinementInterface +.. currentmodule:: pina.callback +.. autoclass:: pina._src.callback.refinement.refinement_interface.RefinementInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/condition/condition.rst b/docs/source/_rst/condition/condition.rst index 51edfafff..cea9371f7 100644 --- a/docs/source/_rst/condition/condition.rst +++ b/docs/source/_rst/condition/condition.rst @@ -2,6 +2,6 @@ Conditions ============= .. currentmodule:: pina.condition.condition -.. autoclass:: Condition +.. autoclass:: pina._src.condition.condition.Condition :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/condition/condition_interface.rst b/docs/source/_rst/condition/condition_interface.rst index 88459629b..6c675c275 100644 --- a/docs/source/_rst/condition/condition_interface.rst +++ b/docs/source/_rst/condition/condition_interface.rst @@ -2,6 +2,6 @@ ConditionInterface ====================== .. currentmodule:: pina.condition.condition_interface -.. autoclass:: ConditionInterface +.. autoclass:: pina._src.condition.condition_interface.ConditionInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/condition/data_condition.rst b/docs/source/_rst/condition/data_condition.rst index b7c322ea1..79d3ea13d 100644 --- a/docs/source/_rst/condition/data_condition.rst +++ b/docs/source/_rst/condition/data_condition.rst @@ -2,14 +2,14 @@ Data Conditions ================== .. currentmodule:: pina.condition.data_condition -.. autoclass:: DataCondition +.. autoclass:: pina._src.condition.data_condition.DataCondition :members: :show-inheritance: -.. autoclass:: GraphDataCondition +.. autoclass:: pina._src.condition.data_condition.GraphDataCondition :members: :show-inheritance: -.. autoclass:: TensorDataCondition +.. autoclass:: pina._src.condition.data_condition.TensorDataCondition :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/condition/domain_equation_condition.rst b/docs/source/_rst/condition/domain_equation_condition.rst index 505c8b839..10f1395ca 100644 --- a/docs/source/_rst/condition/domain_equation_condition.rst +++ b/docs/source/_rst/condition/domain_equation_condition.rst @@ -2,6 +2,6 @@ Domain Equation Condition =========================== .. currentmodule:: pina.condition.domain_equation_condition -.. autoclass:: DomainEquationCondition +.. autoclass:: pina._src.condition.domain_equation_condition.DomainEquationCondition :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/condition/input_equation_condition.rst b/docs/source/_rst/condition/input_equation_condition.rst index 4f5450e93..41b499fff 100644 --- a/docs/source/_rst/condition/input_equation_condition.rst +++ b/docs/source/_rst/condition/input_equation_condition.rst @@ -2,14 +2,14 @@ Input Equation Condition =========================== .. currentmodule:: pina.condition.input_equation_condition -.. autoclass:: InputEquationCondition +.. autoclass:: pina._src.condition.input_equation_condition.InputEquationCondition :members: :show-inheritance: -.. autoclass:: InputTensorEquationCondition +.. autoclass:: pina._src.condition.input_equation_condition.InputTensorEquationCondition :members: :show-inheritance: -.. autoclass:: InputGraphEquationCondition +.. autoclass:: pina._src.condition.input_equation_condition.InputGraphEquationCondition :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/condition/input_target_condition.rst b/docs/source/_rst/condition/input_target_condition.rst index 960b7d6f4..b4bbdcfc3 100644 --- a/docs/source/_rst/condition/input_target_condition.rst +++ b/docs/source/_rst/condition/input_target_condition.rst @@ -2,22 +2,22 @@ Input Target Condition =========================== .. currentmodule:: pina.condition.input_target_condition -.. autoclass:: InputTargetCondition +.. autoclass:: pina._src.condition.input_target_condition.InputTargetCondition :members: :show-inheritance: -.. autoclass:: TensorInputTensorTargetCondition +.. autoclass:: pina._src.condition.input_target_condition.TensorInputTensorTargetCondition :members: :show-inheritance: -.. autoclass:: TensorInputGraphTargetCondition +.. autoclass:: pina._src.condition.input_target_condition.TensorInputGraphTargetCondition :members: :show-inheritance: -.. autoclass:: GraphInputTensorTargetCondition +.. autoclass:: pina._src.condition.input_target_condition.GraphInputTensorTargetCondition :members: :show-inheritance: -.. autoclass:: GraphInputGraphTargetCondition +.. autoclass:: pina._src.condition.input_target_condition.GraphInputGraphTargetCondition :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/data/data_module.rst b/docs/source/_rst/data/data_module.rst index b7ffb14e0..7c57fbf62 100644 --- a/docs/source/_rst/data/data_module.rst +++ b/docs/source/_rst/data/data_module.rst @@ -2,14 +2,14 @@ DataModule ====================== .. currentmodule:: pina.data.data_module -.. autoclass:: Collator +.. autoclass:: pina._src.data.data_module.Collator :members: :show-inheritance: -.. autoclass:: PinaDataModule +.. autoclass:: pina._src.data.data_module.PinaDataModule :members: :show-inheritance: -.. autoclass:: PinaSampler +.. autoclass:: pina._src.data.data_module.PinaSampler :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/data/dataset.rst b/docs/source/_rst/data/dataset.rst index b49b41db1..264722b07 100644 --- a/docs/source/_rst/data/dataset.rst +++ b/docs/source/_rst/data/dataset.rst @@ -2,18 +2,18 @@ Dataset ====================== .. currentmodule:: pina.data.dataset -.. autoclass:: PinaDataset +.. autoclass:: pina._src.data.dataset.PinaDataset :members: :show-inheritance: -.. autoclass:: PinaDatasetFactory +.. autoclass:: pina._src.data.dataset.PinaDatasetFactory :members: :show-inheritance: -.. autoclass:: PinaGraphDataset +.. autoclass:: pina._src.data.dataset.PinaGraphDataset :members: :show-inheritance: -.. autoclass:: PinaTensorDataset +.. autoclass:: pina._src.data.dataset.PinaTensorDataset :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/domain/base_domain.rst b/docs/source/_rst/domain/base_domain.rst index e6b9ce88c..3850ba4fa 100644 --- a/docs/source/_rst/domain/base_domain.rst +++ b/docs/source/_rst/domain/base_domain.rst @@ -2,8 +2,8 @@ BaseDomain =========== .. currentmodule:: pina.domain.base_domain -.. automodule:: pina.domain.base_domain +.. automodule:: pina._src.domain.base_domain -.. autoclass:: BaseDomain +.. autoclass:: pina._src.domain.base_domain.BaseDomain :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/domain/base_operation.rst b/docs/source/_rst/domain/base_operation.rst index cfa145f03..122048d81 100644 --- a/docs/source/_rst/domain/base_operation.rst +++ b/docs/source/_rst/domain/base_operation.rst @@ -2,8 +2,8 @@ BaseOperation ============== .. currentmodule:: pina.domain.base_operation -.. automodule:: pina.domain.base_operation +.. automodule:: pina._src.domain.base_operation -.. autoclass:: BaseOperation +.. autoclass:: pina._src.domain.base_operation.BaseOperation :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/domain/cartesian_domain.rst b/docs/source/_rst/domain/cartesian_domain.rst index 15491be8c..bc2afec03 100644 --- a/docs/source/_rst/domain/cartesian_domain.rst +++ b/docs/source/_rst/domain/cartesian_domain.rst @@ -2,9 +2,9 @@ CartesianDomain ====================== .. currentmodule:: pina.domain.cartesian_domain -.. automodule:: pina.domain.cartesian_domain +.. automodule:: pina._src.domain.cartesian_domain -.. autoclass:: CartesianDomain +.. autoclass:: pina._src.domain.cartesian_domain.CartesianDomain :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/domain/difference.rst b/docs/source/_rst/domain/difference.rst index 0167c3062..91ffd4ec9 100644 --- a/docs/source/_rst/domain/difference.rst +++ b/docs/source/_rst/domain/difference.rst @@ -2,8 +2,8 @@ Difference ====================== .. currentmodule:: pina.domain.difference -.. automodule:: pina.domain.difference +.. automodule:: pina._src.domain.difference -.. autoclass:: Difference +.. autoclass:: pina._src.domain.difference.Difference :members: :show-inheritance: diff --git a/docs/source/_rst/domain/domain_interface.rst b/docs/source/_rst/domain/domain_interface.rst index 898896ba3..96594a23b 100644 --- a/docs/source/_rst/domain/domain_interface.rst +++ b/docs/source/_rst/domain/domain_interface.rst @@ -2,8 +2,8 @@ DomainInterface ================ .. currentmodule:: pina.domain.domain_interface -.. automodule:: pina.domain.domain_interface +.. automodule:: pina._src.domain.domain_interface -.. autoclass:: DomainInterface +.. autoclass:: pina._src.domain.domain_interface.DomainInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/domain/ellipsoid_domain.rst b/docs/source/_rst/domain/ellipsoid_domain.rst index 4a9799e29..2cbc5f7ec 100644 --- a/docs/source/_rst/domain/ellipsoid_domain.rst +++ b/docs/source/_rst/domain/ellipsoid_domain.rst @@ -2,9 +2,9 @@ EllipsoidDomain ====================== .. currentmodule:: pina.domain.ellipsoid_domain -.. automodule:: pina.domain.ellipsoid_domain +.. automodule:: pina._src.domain.ellipsoid_domain -.. autoclass:: EllipsoidDomain +.. autoclass:: pina._src.domain.ellipsoid_domain.EllipsoidDomain :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/domain/exclusion.rst b/docs/source/_rst/domain/exclusion.rst index f624122ae..040b48416 100644 --- a/docs/source/_rst/domain/exclusion.rst +++ b/docs/source/_rst/domain/exclusion.rst @@ -2,8 +2,8 @@ Exclusion ====================== .. currentmodule:: pina.domain.exclusion -.. automodule:: pina.domain.exclusion +.. automodule:: pina._src.domain.exclusion -.. autoclass:: Exclusion +.. autoclass:: pina._src.domain.exclusion.Exclusion :members: :show-inheritance: diff --git a/docs/source/_rst/domain/intersection.rst b/docs/source/_rst/domain/intersection.rst index fade1d042..666fe0f00 100644 --- a/docs/source/_rst/domain/intersection.rst +++ b/docs/source/_rst/domain/intersection.rst @@ -2,8 +2,8 @@ Intersection ====================== .. currentmodule:: pina.domain.intersection -.. automodule:: pina.domain.intersection +.. automodule:: pina._src.domain.intersection -.. autoclass:: Intersection +.. autoclass:: pina._src.domain.intersection.Intersection :members: :show-inheritance: diff --git a/docs/source/_rst/domain/operation_interface.rst b/docs/source/_rst/domain/operation_interface.rst index 0acd393dc..42e92fbe8 100644 --- a/docs/source/_rst/domain/operation_interface.rst +++ b/docs/source/_rst/domain/operation_interface.rst @@ -2,8 +2,8 @@ OperationInterface ====================== .. currentmodule:: pina.domain.operation_interface -.. automodule:: pina.domain.operation_interface +.. automodule:: pina._src.domain.operation_interface -.. autoclass:: OperationInterface +.. autoclass:: pina._src.domain.operation_interface.OperationInterface :members: :show-inheritance: diff --git a/docs/source/_rst/domain/simplex_domain.rst b/docs/source/_rst/domain/simplex_domain.rst index 5f1d31c9b..0aba5f912 100644 --- a/docs/source/_rst/domain/simplex_domain.rst +++ b/docs/source/_rst/domain/simplex_domain.rst @@ -2,9 +2,9 @@ SimplexDomain ====================== .. currentmodule:: pina.domain.simplex_domain -.. automodule:: pina.domain.simplex_domain +.. automodule:: pina._src.domain.simplex_domain -.. autoclass:: SimplexDomain +.. autoclass:: pina._src.domain.simplex_domain.SimplexDomain :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/domain/union.rst b/docs/source/_rst/domain/union.rst index 614bb351c..fc5ff92a9 100644 --- a/docs/source/_rst/domain/union.rst +++ b/docs/source/_rst/domain/union.rst @@ -2,8 +2,8 @@ Union ====================== .. currentmodule:: pina.domain.union -.. automodule:: pina.domain.union +.. automodule:: pina._src.domain.union -.. autoclass:: Union +.. autoclass:: pina._src.domain.union.Union :members: :show-inheritance: diff --git a/docs/source/_rst/equation/equation.rst b/docs/source/_rst/equation/equation.rst index 33e19c957..edb350090 100644 --- a/docs/source/_rst/equation/equation.rst +++ b/docs/source/_rst/equation/equation.rst @@ -2,6 +2,6 @@ Equation ========== .. currentmodule:: pina.equation.equation -.. autoclass:: Equation +.. autoclass:: pina._src.equation.equation.Equation :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/equation/equation_factory.rst b/docs/source/_rst/equation/equation_factory.rst index 86390c6bd..5282aa948 100644 --- a/docs/source/_rst/equation/equation_factory.rst +++ b/docs/source/_rst/equation/equation_factory.rst @@ -2,42 +2,42 @@ Equation Factory ================== .. currentmodule:: pina.equation.equation_factory -.. autoclass:: FixedValue +.. autoclass:: pina._src.equation.equation_factory.FixedValue :members: :show-inheritance: -.. autoclass:: FixedGradient +.. autoclass:: pina._src.equation.equation_factory.FixedGradient :members: :show-inheritance: -.. autoclass:: FixedFlux +.. autoclass:: pina._src.equation.equation_factory.FixedFlux :members: :show-inheritance: -.. autoclass:: FixedLaplacian +.. autoclass:: pina._src.equation.equation_factory.FixedLaplacian :members: :show-inheritance: -.. autoclass:: Laplace +.. autoclass:: pina._src.equation.equation_factory.Laplace :members: :show-inheritance: -.. autoclass:: Advection +.. autoclass:: pina._src.equation.equation_factory.Advection :members: :show-inheritance: -.. autoclass:: AllenCahn +.. autoclass:: pina._src.equation.equation_factory.AllenCahn :members: :show-inheritance: -.. autoclass:: DiffusionReaction +.. autoclass:: pina._src.equation.equation_factory.DiffusionReaction :members: :show-inheritance: -.. autoclass:: Helmholtz +.. autoclass:: pina._src.equation.equation_factory.Helmholtz :members: :show-inheritance: -.. autoclass:: Poisson +.. autoclass:: pina._src.equation.equation_factory.Poisson :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/equation/equation_interface.rst b/docs/source/_rst/equation/equation_interface.rst index cde7b0012..f16502831 100644 --- a/docs/source/_rst/equation/equation_interface.rst +++ b/docs/source/_rst/equation/equation_interface.rst @@ -2,6 +2,6 @@ Equation Interface ==================== .. currentmodule:: pina.equation.equation_interface -.. autoclass:: EquationInterface +.. autoclass:: pina._src.equation.equation_interface.EquationInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/equation/system_equation.rst b/docs/source/_rst/equation/system_equation.rst index 33c931cd9..88d1554f8 100644 --- a/docs/source/_rst/equation/system_equation.rst +++ b/docs/source/_rst/equation/system_equation.rst @@ -2,6 +2,6 @@ System Equation ================= .. currentmodule:: pina.equation.system_equation -.. autoclass:: SystemEquation +.. autoclass:: pina._src.equation.system_equation.SystemEquation :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/graph/graph.rst b/docs/source/_rst/graph/graph.rst index 1921f83e0..58180f50f 100644 --- a/docs/source/_rst/graph/graph.rst +++ b/docs/source/_rst/graph/graph.rst @@ -3,7 +3,7 @@ Graph .. currentmodule:: pina.graph -.. autoclass:: Graph +.. autoclass:: pina._src.core.graph.Graph :members: :private-members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/graph/graph_builder.rst b/docs/source/_rst/graph/graph_builder.rst index 2508aecb7..f576fe7c7 100644 --- a/docs/source/_rst/graph/graph_builder.rst +++ b/docs/source/_rst/graph/graph_builder.rst @@ -3,7 +3,7 @@ GraphBuilder .. currentmodule:: pina.graph -.. autoclass:: GraphBuilder +.. autoclass:: pina._src.core.graph.GraphBuilder :members: :private-members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/graph/knn_graph.rst b/docs/source/_rst/graph/knn_graph.rst index 8ef0b190b..e31a004ab 100644 --- a/docs/source/_rst/graph/knn_graph.rst +++ b/docs/source/_rst/graph/knn_graph.rst @@ -3,7 +3,7 @@ KNNGraph .. currentmodule:: pina.graph -.. autoclass:: KNNGraph +.. autoclass:: pina._src.core.graph.KNNGraph :members: :private-members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/graph/label_batch.rst b/docs/source/_rst/graph/label_batch.rst index 7cd4d2684..5a68bde60 100644 --- a/docs/source/_rst/graph/label_batch.rst +++ b/docs/source/_rst/graph/label_batch.rst @@ -3,7 +3,7 @@ LabelBatch .. currentmodule:: pina.graph -.. autoclass:: LabelBatch +.. autoclass:: pina._src.core.graph.LabelBatch :members: :private-members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/graph/radius_graph.rst b/docs/source/_rst/graph/radius_graph.rst index 7414d2dc1..9db9fb174 100644 --- a/docs/source/_rst/graph/radius_graph.rst +++ b/docs/source/_rst/graph/radius_graph.rst @@ -3,7 +3,7 @@ RadiusGraph .. currentmodule:: pina.graph -.. autoclass:: RadiusGraph +.. autoclass:: pina._src.core.graph.RadiusGraph :members: :private-members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/label_tensor.rst b/docs/source/_rst/label_tensor.rst index 9eb227369..1b750ad97 100644 --- a/docs/source/_rst/label_tensor.rst +++ b/docs/source/_rst/label_tensor.rst @@ -2,8 +2,11 @@ LabelTensor =========== .. currentmodule:: pina.label_tensor +.. automodule:: pina._src.core.label_tensor + :no-members: -.. autoclass:: LabelTensor + +.. autoclass:: pina._src.core.label_tensor.LabelTensor :members: :private-members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/linear_weighting.rst b/docs/source/_rst/loss/linear_weighting.rst index 16e6232d0..359a4fbd1 100644 --- a/docs/source/_rst/loss/linear_weighting.rst +++ b/docs/source/_rst/loss/linear_weighting.rst @@ -1,9 +1,11 @@ LinearWeighting ============================= -.. currentmodule:: pina.loss.linear_weighting -.. automodule:: pina.loss.linear_weighting +.. currentmodule:: pina.loss -.. autoclass:: LinearWeighting +.. automodule:: pina._src.loss.linear_weighting + :no-members: + +.. autoclass:: pina._src.loss.linear_weighting.LinearWeighting :members: - :show-inheritance: + :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/loss_interface.rst b/docs/source/_rst/loss/loss_interface.rst index 8ff78c01e..76a84d9c6 100644 --- a/docs/source/_rst/loss/loss_interface.rst +++ b/docs/source/_rst/loss/loss_interface.rst @@ -2,8 +2,8 @@ LossInterface =============== .. currentmodule:: pina.loss.loss_interface -.. automodule:: pina.loss.loss_interface +.. automodule:: pina._src.loss.loss_interface -.. autoclass:: LossInterface +.. autoclass:: pina._src.loss.loss_interface.LossInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/lploss.rst b/docs/source/_rst/loss/lploss.rst index 37dfdfe3c..9f6113a71 100644 --- a/docs/source/_rst/loss/lploss.rst +++ b/docs/source/_rst/loss/lploss.rst @@ -2,6 +2,9 @@ LpLoss =============== .. currentmodule:: pina.loss.lp_loss -.. autoclass:: LpLoss +.. automodule:: pina._src.loss.lp_loss + :no-members: + +.. autoclass:: pina._src.loss.lp_loss.LpLoss :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/ntk_weighting.rst b/docs/source/_rst/loss/ntk_weighting.rst index 6d9d8816d..488e1923f 100644 --- a/docs/source/_rst/loss/ntk_weighting.rst +++ b/docs/source/_rst/loss/ntk_weighting.rst @@ -2,8 +2,8 @@ NeuralTangentKernelWeighting ============================= .. currentmodule:: pina.loss.ntk_weighting -.. automodule:: pina.loss.ntk_weighting +.. automodule:: pina._src.loss.ntk_weighting -.. autoclass:: NeuralTangentKernelWeighting +.. autoclass:: pina._src.loss.ntk_weighting.NeuralTangentKernelWeighting :members: :show-inheritance: diff --git a/docs/source/_rst/loss/powerloss.rst b/docs/source/_rst/loss/powerloss.rst index e4dee43b8..7a1438f4c 100644 --- a/docs/source/_rst/loss/powerloss.rst +++ b/docs/source/_rst/loss/powerloss.rst @@ -2,6 +2,8 @@ PowerLoss ==================== .. currentmodule:: pina.loss.power_loss -.. autoclass:: PowerLoss +.. automodule:: pina._src.loss.power_loss + +.. autoclass:: pina._src.loss.power_loss.PowerLoss :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/scalar_weighting.rst b/docs/source/_rst/loss/scalar_weighting.rst index 5ee82a785..bbf8c06ec 100644 --- a/docs/source/_rst/loss/scalar_weighting.rst +++ b/docs/source/_rst/loss/scalar_weighting.rst @@ -2,8 +2,8 @@ ScalarWeighting =================== .. currentmodule:: pina.loss.scalar_weighting -.. automodule:: pina.loss.scalar_weighting +.. automodule:: pina._src.loss.scalar_weighting -.. autoclass:: ScalarWeighting +.. autoclass:: pina._src.loss.scalar_weighting.ScalarWeighting :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/self_adaptive_weighting.rst b/docs/source/_rst/loss/self_adaptive_weighting.rst index cd1daed1f..6c39873d6 100644 --- a/docs/source/_rst/loss/self_adaptive_weighting.rst +++ b/docs/source/_rst/loss/self_adaptive_weighting.rst @@ -2,8 +2,8 @@ SelfAdaptiveWeighting ============================= .. currentmodule:: pina.loss.self_adaptive_weighting -.. automodule:: pina.loss.self_adaptive_weighting +.. automodule:: pina._src.loss.self_adaptive_weighting -.. autoclass:: SelfAdaptiveWeighting +.. autoclass:: pina._src.loss.self_adaptive_weighting.SelfAdaptiveWeighting :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/loss/weighting_interface.rst b/docs/source/_rst/loss/weighting_interface.rst index 2b0fa1bdc..d4aedd9d3 100644 --- a/docs/source/_rst/loss/weighting_interface.rst +++ b/docs/source/_rst/loss/weighting_interface.rst @@ -2,8 +2,8 @@ WeightingInterface =================== .. currentmodule:: pina.loss.weighting_interface -.. automodule:: pina.loss.weighting_interface +.. automodule:: pina._src.loss.weighting_interface -.. autoclass:: WeightingInterface +.. autoclass:: pina._src.loss.weighting_interface.WeightingInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/average_neural_operator.rst b/docs/source/_rst/model/average_neural_operator.rst index 02211e9a8..a54107620 100644 --- a/docs/source/_rst/model/average_neural_operator.rst +++ b/docs/source/_rst/model/average_neural_operator.rst @@ -2,6 +2,6 @@ Averaging Neural Operator ============================== .. currentmodule:: pina.model.average_neural_operator -.. autoclass:: AveragingNeuralOperator +.. autoclass:: pina._src.model.average_neural_operator.AveragingNeuralOperator :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/block/average_neural_operator_block.rst b/docs/source/_rst/model/block/average_neural_operator_block.rst index 0072ec9d0..1e38fc215 100644 --- a/docs/source/_rst/model/block/average_neural_operator_block.rst +++ b/docs/source/_rst/model/block/average_neural_operator_block.rst @@ -2,7 +2,7 @@ Averaging Neural Operator Block ================================== .. currentmodule:: pina.model.block.average_neural_operator_block -.. autoclass:: AVNOBlock +.. autoclass:: pina._src.model.block.average_neural_operator_block.AVNOBlock :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/model/block/convolution.rst b/docs/source/_rst/model/block/convolution.rst index 4033d5d56..bd0d32e71 100644 --- a/docs/source/_rst/model/block/convolution.rst +++ b/docs/source/_rst/model/block/convolution.rst @@ -2,7 +2,7 @@ Continuous Convolution Block =============================== .. currentmodule:: pina.model.block.convolution_2d -.. autoclass:: ContinuousConvBlock +.. autoclass:: pina._src.model.block.convolution_2d.ContinuousConvBlock :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/model/block/convolution_interface.rst b/docs/source/_rst/model/block/convolution_interface.rst index f8e61c16c..c6708ca94 100644 --- a/docs/source/_rst/model/block/convolution_interface.rst +++ b/docs/source/_rst/model/block/convolution_interface.rst @@ -2,7 +2,7 @@ Continuous Convolution Interface ================================== .. currentmodule:: pina.model.block.convolution -.. autoclass:: BaseContinuousConv +.. autoclass:: pina._src.model.block.convolution.BaseContinuousConv :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/model/block/enhanced_linear.rst b/docs/source/_rst/model/block/enhanced_linear.rst index d08cf79bf..92e8d5581 100644 --- a/docs/source/_rst/model/block/enhanced_linear.rst +++ b/docs/source/_rst/model/block/enhanced_linear.rst @@ -2,7 +2,7 @@ EnhancedLinear Block ===================== .. currentmodule:: pina.model.block.residual -.. autoclass:: EnhancedLinear +.. autoclass:: pina._src.model.block.residual.EnhancedLinear :members: :show-inheritance: :noindex: \ No newline at end of file diff --git a/docs/source/_rst/model/block/fourier_block.rst b/docs/source/_rst/model/block/fourier_block.rst index c0fff4deb..9b601bb3d 100644 --- a/docs/source/_rst/model/block/fourier_block.rst +++ b/docs/source/_rst/model/block/fourier_block.rst @@ -3,14 +3,14 @@ Fourier Neural Operator Block .. currentmodule:: pina.model.block.fourier_block -.. autoclass:: FourierBlock1D +.. autoclass:: pina._src.model.block.fourier_block.FourierBlock1D :members: :show-inheritance: -.. autoclass:: FourierBlock2D +.. autoclass:: pina._src.model.block.fourier_block.FourierBlock2D :members: :show-inheritance: -.. autoclass:: FourierBlock3D +.. autoclass:: pina._src.model.block.fourier_block.FourierBlock3D :members: :show-inheritance: diff --git a/docs/source/_rst/model/block/fourier_embedding.rst b/docs/source/_rst/model/block/fourier_embedding.rst index 77eb3960c..48c8df41c 100644 --- a/docs/source/_rst/model/block/fourier_embedding.rst +++ b/docs/source/_rst/model/block/fourier_embedding.rst @@ -2,7 +2,7 @@ Fourier Feature Embedding ======================================= .. currentmodule:: pina.model.block.embedding -.. autoclass:: FourierFeatureEmbedding +.. autoclass:: pina._src.model.block.embedding.FourierFeatureEmbedding :members: :show-inheritance: diff --git a/docs/source/_rst/model/block/gno_block.rst b/docs/source/_rst/model/block/gno_block.rst index 19a532bab..8ce3f2f30 100644 --- a/docs/source/_rst/model/block/gno_block.rst +++ b/docs/source/_rst/model/block/gno_block.rst @@ -2,7 +2,7 @@ Graph Neural Operator Block =============================== .. currentmodule:: pina.model.block.gno_block -.. autoclass:: GNOBlock +.. autoclass:: pina._src.model.block.gno_block.GNOBlock :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/model/block/low_rank_block.rst b/docs/source/_rst/model/block/low_rank_block.rst index 366068f79..83c7a11a0 100644 --- a/docs/source/_rst/model/block/low_rank_block.rst +++ b/docs/source/_rst/model/block/low_rank_block.rst @@ -2,7 +2,7 @@ Low Rank Neural Operator Block ================================= .. currentmodule:: pina.model.block.low_rank_block -.. autoclass:: LowRankBlock +.. autoclass:: pina._src.model.block.low_rank_block.LowRankBlock :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/model/block/message_passing/deep_tensor_network_block.rst b/docs/source/_rst/model/block/message_passing/deep_tensor_network_block.rst index 30121e5a6..51482496a 100644 --- a/docs/source/_rst/model/block/message_passing/deep_tensor_network_block.rst +++ b/docs/source/_rst/model/block/message_passing/deep_tensor_network_block.rst @@ -2,7 +2,7 @@ Deep Tensor Network Block ================================== .. currentmodule:: pina.model.block.message_passing.deep_tensor_network_block -.. autoclass:: DeepTensorNetworkBlock +.. autoclass:: pina._src.model.block.message_passing.deep_tensor_network_block.DeepTensorNetworkBlock :members: :show-inheritance: :noindex: diff --git a/docs/source/_rst/model/block/message_passing/en_equivariant_network_block.rst b/docs/source/_rst/model/block/message_passing/en_equivariant_network_block.rst index e2755c665..09966ea0a 100644 --- a/docs/source/_rst/model/block/message_passing/en_equivariant_network_block.rst +++ b/docs/source/_rst/model/block/message_passing/en_equivariant_network_block.rst @@ -2,7 +2,7 @@ E(n) Equivariant Network Block ================================== .. currentmodule:: pina.model.block.message_passing.en_equivariant_network_block -.. autoclass:: EnEquivariantNetworkBlock +.. autoclass:: pina._src.model.block.message_passing.en_equivariant_network_block.EnEquivariantNetworkBlock :members: :show-inheritance: :noindex: \ No newline at end of file diff --git a/docs/source/_rst/model/block/message_passing/equivariant_graph_neural_operator_block.rst b/docs/source/_rst/model/block/message_passing/equivariant_graph_neural_operator_block.rst index 8d047f84e..b61c4f430 100644 --- a/docs/source/_rst/model/block/message_passing/equivariant_graph_neural_operator_block.rst +++ b/docs/source/_rst/model/block/message_passing/equivariant_graph_neural_operator_block.rst @@ -2,6 +2,6 @@ EquivariantGraphNeuralOperatorBlock ===================================== .. currentmodule:: pina.model.block.message_passing.equivariant_graph_neural_operator_block -.. autoclass:: EquivariantGraphNeuralOperatorBlock +.. autoclass:: pina._src.model.block.message_passing.equivariant_graph_neural_operator_block.EquivariantGraphNeuralOperatorBlock :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/block/message_passing/interaction_network_block.rst b/docs/source/_rst/model/block/message_passing/interaction_network_block.rst index ffac307e2..a4c86e562 100644 --- a/docs/source/_rst/model/block/message_passing/interaction_network_block.rst +++ b/docs/source/_rst/model/block/message_passing/interaction_network_block.rst @@ -2,7 +2,7 @@ Interaction Network Block ================================== .. currentmodule:: pina.model.block.message_passing.interaction_network_block -.. autoclass:: InteractionNetworkBlock +.. autoclass:: pina._src.model.block.message_passing.interaction_network_block.InteractionNetworkBlock :members: :show-inheritance: :noindex: \ No newline at end of file diff --git a/docs/source/_rst/model/block/message_passing/radial_field_network_block.rst b/docs/source/_rst/model/block/message_passing/radial_field_network_block.rst index e05203f33..bb66ee770 100644 --- a/docs/source/_rst/model/block/message_passing/radial_field_network_block.rst +++ b/docs/source/_rst/model/block/message_passing/radial_field_network_block.rst @@ -2,7 +2,7 @@ Radial Field Network Block ================================== .. currentmodule:: pina.model.block.message_passing.radial_field_network_block -.. autoclass:: RadialFieldNetworkBlock +.. autoclass:: pina._src.model.block.message_passing.radial_field_network_block.RadialFieldNetworkBlock :members: :show-inheritance: :noindex: \ No newline at end of file diff --git a/docs/source/_rst/model/block/orthogonal.rst b/docs/source/_rst/model/block/orthogonal.rst index 21d12998a..a9fc727fb 100644 --- a/docs/source/_rst/model/block/orthogonal.rst +++ b/docs/source/_rst/model/block/orthogonal.rst @@ -2,6 +2,6 @@ Orthogonal Block ====================== .. currentmodule:: pina.model.block.orthogonal -.. autoclass:: OrthogonalBlock +.. autoclass:: pina._src.model.block.orthogonal.OrthogonalBlock :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/block/pbc_embedding.rst b/docs/source/_rst/model/block/pbc_embedding.rst index f469644af..e79ae9514 100644 --- a/docs/source/_rst/model/block/pbc_embedding.rst +++ b/docs/source/_rst/model/block/pbc_embedding.rst @@ -2,7 +2,7 @@ Periodic Boundary Condition Embedding ======================================= .. currentmodule:: pina.model.block.embedding -.. autoclass:: PeriodicBoundaryEmbedding +.. autoclass:: pina._src.model.block.embedding.PeriodicBoundaryEmbedding :members: :show-inheritance: diff --git a/docs/source/_rst/model/block/pirate_network_block.rst b/docs/source/_rst/model/block/pirate_network_block.rst index 5d0428a68..f534d3cb0 100644 --- a/docs/source/_rst/model/block/pirate_network_block.rst +++ b/docs/source/_rst/model/block/pirate_network_block.rst @@ -2,7 +2,7 @@ PirateNet Block ======================================= .. currentmodule:: pina.model.block.pirate_network_block -.. autoclass:: PirateNetBlock +.. autoclass:: pina._src.model.block.pirate_network_block.PirateNetBlock :members: :show-inheritance: diff --git a/docs/source/_rst/model/block/pod_block.rst b/docs/source/_rst/model/block/pod_block.rst index 4b66e2c97..98fadbb1e 100644 --- a/docs/source/_rst/model/block/pod_block.rst +++ b/docs/source/_rst/model/block/pod_block.rst @@ -2,6 +2,6 @@ Proper Orthogonal Decomposition Block ============================================ .. currentmodule:: pina.model.block.pod_block -.. autoclass:: PODBlock +.. autoclass:: pina._src.model.block.pod_block.PODBlock :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/block/rbf_block.rst b/docs/source/_rst/model/block/rbf_block.rst index 545f14d08..b8997d21b 100644 --- a/docs/source/_rst/model/block/rbf_block.rst +++ b/docs/source/_rst/model/block/rbf_block.rst @@ -2,6 +2,6 @@ Radias Basis Function Block ============================= .. currentmodule:: pina.model.block.rbf_block -.. autoclass:: RBFBlock +.. autoclass:: pina._src.model.block.rbf_block.RBFBlock :members: :show-inheritance: diff --git a/docs/source/_rst/model/block/residual.rst b/docs/source/_rst/model/block/residual.rst index 69741c74c..d0e478563 100644 --- a/docs/source/_rst/model/block/residual.rst +++ b/docs/source/_rst/model/block/residual.rst @@ -2,6 +2,6 @@ Residual Block =================== .. currentmodule:: pina.model.block.residual -.. autoclass:: ResidualBlock +.. autoclass:: pina._src.model.block.residual.ResidualBlock :members: :show-inheritance: diff --git a/docs/source/_rst/model/block/spectral.rst b/docs/source/_rst/model/block/spectral.rst index 3c80f3dd8..1ee0e1d19 100644 --- a/docs/source/_rst/model/block/spectral.rst +++ b/docs/source/_rst/model/block/spectral.rst @@ -2,14 +2,14 @@ Spectral Convolution Block ============================ .. currentmodule:: pina.model.block.spectral -.. autoclass:: SpectralConvBlock1D +.. autoclass:: pina._src.model.block.spectral.SpectralConvBlock1D :members: :show-inheritance: -.. autoclass:: SpectralConvBlock2D +.. autoclass:: pina._src.model.block.spectral.SpectralConvBlock2D :members: :show-inheritance: -.. autoclass:: SpectralConvBlock3D +.. autoclass:: pina._src.model.block.spectral.SpectralConvBlock3D :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/deeponet.rst b/docs/source/_rst/model/deeponet.rst index 0ca08242d..eef25dcae 100644 --- a/docs/source/_rst/model/deeponet.rst +++ b/docs/source/_rst/model/deeponet.rst @@ -2,6 +2,6 @@ DeepONet =========== .. currentmodule:: pina.model.deeponet -.. autoclass:: DeepONet +.. autoclass:: pina._src.model.deeponet.DeepONet :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/equivariant_graph_neural_operator.rst b/docs/source/_rst/model/equivariant_graph_neural_operator.rst index a11edcc00..e100f5c1e 100644 --- a/docs/source/_rst/model/equivariant_graph_neural_operator.rst +++ b/docs/source/_rst/model/equivariant_graph_neural_operator.rst @@ -2,6 +2,6 @@ EquivariantGraphNeuralOperator ================================= .. currentmodule:: pina.model.equivariant_graph_neural_operator -.. autoclass:: EquivariantGraphNeuralOperator +.. autoclass:: pina._src.model.equivariant_graph_neural_operator.EquivariantGraphNeuralOperator :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/feed_forward.rst b/docs/source/_rst/model/feed_forward.rst index 2dea8e550..be75ed70b 100644 --- a/docs/source/_rst/model/feed_forward.rst +++ b/docs/source/_rst/model/feed_forward.rst @@ -2,6 +2,6 @@ FeedForward ====================== .. currentmodule:: pina.model.feed_forward -.. autoclass:: FeedForward +.. autoclass:: pina._src.model.feed_forward.FeedForward :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/fourier_integral_kernel.rst b/docs/source/_rst/model/fourier_integral_kernel.rst index b1fb484fe..dba63c429 100644 --- a/docs/source/_rst/model/fourier_integral_kernel.rst +++ b/docs/source/_rst/model/fourier_integral_kernel.rst @@ -2,6 +2,6 @@ FourierIntegralKernel ========================= .. currentmodule:: pina.model.fourier_neural_operator -.. autoclass:: FourierIntegralKernel +.. autoclass:: pina._src.model.fourier_neural_operator.FourierIntegralKernel :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/fourier_neural_operator.rst b/docs/source/_rst/model/fourier_neural_operator.rst index e77494fd0..14cb52667 100644 --- a/docs/source/_rst/model/fourier_neural_operator.rst +++ b/docs/source/_rst/model/fourier_neural_operator.rst @@ -2,6 +2,6 @@ FNO =========== .. currentmodule:: pina.model.fourier_neural_operator -.. autoclass:: FNO +.. autoclass:: pina._src.model.fourier_neural_operator.FNO :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/graph_neural_operator.rst b/docs/source/_rst/model/graph_neural_operator.rst index fbb8600e5..7f7b7ed6b 100644 --- a/docs/source/_rst/model/graph_neural_operator.rst +++ b/docs/source/_rst/model/graph_neural_operator.rst @@ -2,6 +2,6 @@ GraphNeuralOperator ======================= .. currentmodule:: pina.model.graph_neural_operator -.. autoclass:: GraphNeuralOperator +.. autoclass:: pina._src.model.graph_neural_operator.GraphNeuralOperator :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/graph_neural_operator_integral_kernel.rst b/docs/source/_rst/model/graph_neural_operator_integral_kernel.rst index cf15a31a5..45f78c366 100644 --- a/docs/source/_rst/model/graph_neural_operator_integral_kernel.rst +++ b/docs/source/_rst/model/graph_neural_operator_integral_kernel.rst @@ -2,6 +2,6 @@ GraphNeuralKernel ======================= .. currentmodule:: pina.model.graph_neural_operator -.. autoclass:: GraphNeuralKernel +.. autoclass:: pina._src.model.graph_neural_operator.GraphNeuralKernel :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/kernel_neural_operator.rst b/docs/source/_rst/model/kernel_neural_operator.rst index d693afac5..75a39b223 100644 --- a/docs/source/_rst/model/kernel_neural_operator.rst +++ b/docs/source/_rst/model/kernel_neural_operator.rst @@ -2,6 +2,6 @@ KernelNeuralOperator ======================= .. currentmodule:: pina.model.kernel_neural_operator -.. autoclass:: KernelNeuralOperator +.. autoclass:: pina._src.model.kernel_neural_operator.KernelNeuralOperator :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/low_rank_neural_operator.rst b/docs/source/_rst/model/low_rank_neural_operator.rst index 22fe7cc93..e0362d144 100644 --- a/docs/source/_rst/model/low_rank_neural_operator.rst +++ b/docs/source/_rst/model/low_rank_neural_operator.rst @@ -2,6 +2,6 @@ Low Rank Neural Operator ============================== .. currentmodule:: pina.model.low_rank_neural_operator -.. autoclass:: LowRankNeuralOperator +.. autoclass:: pina._src.model.low_rank_neural_operator.LowRankNeuralOperator :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/mionet.rst b/docs/source/_rst/model/mionet.rst index fe6281710..1888d911e 100644 --- a/docs/source/_rst/model/mionet.rst +++ b/docs/source/_rst/model/mionet.rst @@ -2,6 +2,6 @@ MIONet =========== .. currentmodule:: pina.model.deeponet -.. autoclass:: MIONet +.. autoclass:: pina._src.model.deeponet.MIONet :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/multi_feed_forward.rst b/docs/source/_rst/model/multi_feed_forward.rst index aa79580ee..458173ced 100644 --- a/docs/source/_rst/model/multi_feed_forward.rst +++ b/docs/source/_rst/model/multi_feed_forward.rst @@ -2,6 +2,6 @@ MultiFeedForward ================== .. currentmodule:: pina.model.multi_feed_forward -.. autoclass:: MultiFeedForward +.. autoclass:: pina._src.model.multi_feed_forward.MultiFeedForward :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/pirate_network.rst b/docs/source/_rst/model/pirate_network.rst index 5b374c247..a60449a6c 100644 --- a/docs/source/_rst/model/pirate_network.rst +++ b/docs/source/_rst/model/pirate_network.rst @@ -2,6 +2,6 @@ PirateNet ======================= .. currentmodule:: pina.model.pirate_network -.. autoclass:: PirateNet +.. autoclass:: pina._src.model.pirate_network.PirateNet :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/residual_feed_forward.rst b/docs/source/_rst/model/residual_feed_forward.rst index 66d83a42c..d8ce08152 100644 --- a/docs/source/_rst/model/residual_feed_forward.rst +++ b/docs/source/_rst/model/residual_feed_forward.rst @@ -2,6 +2,6 @@ ResidualFeedForward ====================== .. currentmodule:: pina.model.feed_forward -.. autoclass:: ResidualFeedForward +.. autoclass:: pina._src.model.feed_forward.ResidualFeedForward :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/sindy.rst b/docs/source/_rst/model/sindy.rst index bd507603b..f07ca6d30 100644 --- a/docs/source/_rst/model/sindy.rst +++ b/docs/source/_rst/model/sindy.rst @@ -2,6 +2,6 @@ SINDy ======================= .. currentmodule:: pina.model.sindy -.. autoclass:: SINDy +.. autoclass:: pina._src.model.sindy.SINDy :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/spline.rst b/docs/source/_rst/model/spline.rst index aa7450b70..278a95d3b 100644 --- a/docs/source/_rst/model/spline.rst +++ b/docs/source/_rst/model/spline.rst @@ -2,6 +2,6 @@ Spline ======== .. currentmodule:: pina.model.spline -.. autoclass:: Spline +.. autoclass:: pina._src.model.spline.Spline :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/model/spline_surface.rst b/docs/source/_rst/model/spline_surface.rst index 6bbf137d8..9b204cd22 100644 --- a/docs/source/_rst/model/spline_surface.rst +++ b/docs/source/_rst/model/spline_surface.rst @@ -2,6 +2,6 @@ Spline Surface ================ .. currentmodule:: pina.model.spline_surface -.. autoclass:: SplineSurface +.. autoclass:: pina._src.model.spline_surface.SplineSurface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/operator.rst b/docs/source/_rst/operator.rst index 42746a6f8..fe0ad0398 100644 --- a/docs/source/_rst/operator.rst +++ b/docs/source/_rst/operator.rst @@ -3,6 +3,7 @@ Operators .. currentmodule:: pina.operator -.. automodule:: pina.operator + +.. automodule:: pina._src.core.operator :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/optim/optimizer_interface.rst b/docs/source/_rst/optim/optimizer_interface.rst index 88c18e8f5..afd62f6a0 100644 --- a/docs/source/_rst/optim/optimizer_interface.rst +++ b/docs/source/_rst/optim/optimizer_interface.rst @@ -2,6 +2,6 @@ Optimizer ============ .. currentmodule:: pina.optim.optimizer_interface -.. autoclass:: Optimizer +.. autoclass:: pina._src.optim.optimizer_interface.Optimizer :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/optim/scheduler_interface.rst b/docs/source/_rst/optim/scheduler_interface.rst index ab8ee292e..0795c34e3 100644 --- a/docs/source/_rst/optim/scheduler_interface.rst +++ b/docs/source/_rst/optim/scheduler_interface.rst @@ -2,6 +2,6 @@ Scheduler ============= .. currentmodule:: pina.optim.scheduler_interface -.. autoclass:: Scheduler +.. autoclass:: pina._src.optim.scheduler_interface.Scheduler :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/optim/torch_optimizer.rst b/docs/source/_rst/optim/torch_optimizer.rst index 3e6c9d912..67ab59164 100644 --- a/docs/source/_rst/optim/torch_optimizer.rst +++ b/docs/source/_rst/optim/torch_optimizer.rst @@ -2,6 +2,6 @@ TorchOptimizer =============== .. currentmodule:: pina.optim.torch_optimizer -.. autoclass:: TorchOptimizer +.. autoclass:: pina._src.optim.torch_optimizer.TorchOptimizer :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/optim/torch_scheduler.rst b/docs/source/_rst/optim/torch_scheduler.rst index 5c3e4df36..272ba631f 100644 --- a/docs/source/_rst/optim/torch_scheduler.rst +++ b/docs/source/_rst/optim/torch_scheduler.rst @@ -2,6 +2,6 @@ TorchScheduler =============== .. currentmodule:: pina.optim.torch_scheduler -.. autoclass:: TorchScheduler +.. autoclass:: pina._src.optim.torch_scheduler.TorchScheduler :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/problem/abstract_problem.rst b/docs/source/_rst/problem/abstract_problem.rst index 143909e1b..ae5e5f26e 100644 --- a/docs/source/_rst/problem/abstract_problem.rst +++ b/docs/source/_rst/problem/abstract_problem.rst @@ -2,8 +2,8 @@ AbstractProblem =============== .. currentmodule:: pina.problem.abstract_problem -.. automodule:: pina.problem.abstract_problem +.. automodule:: pina._src.problem.abstract_problem -.. autoclass:: AbstractProblem +.. autoclass:: pina._src.problem.abstract_problem.AbstractProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/inverse_problem.rst b/docs/source/_rst/problem/inverse_problem.rst index 5ce306ffc..4b5de05cb 100644 --- a/docs/source/_rst/problem/inverse_problem.rst +++ b/docs/source/_rst/problem/inverse_problem.rst @@ -2,8 +2,8 @@ InverseProblem ============== .. currentmodule:: pina.problem.inverse_problem -.. automodule:: pina.problem.inverse_problem +.. automodule:: pina._src.problem.inverse_problem -.. autoclass:: InverseProblem +.. autoclass:: pina._src.problem.inverse_problem.InverseProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/parametric_problem.rst b/docs/source/_rst/problem/parametric_problem.rst index 8f217fbbe..1a5e83490 100644 --- a/docs/source/_rst/problem/parametric_problem.rst +++ b/docs/source/_rst/problem/parametric_problem.rst @@ -2,8 +2,8 @@ ParametricProblem ==================== .. currentmodule:: pina.problem.parametric_problem -.. automodule:: pina.problem.parametric_problem +.. automodule:: pina._src.problem.parametric_problem -.. autoclass:: ParametricProblem +.. autoclass:: pina._src.problem.parametric_problem.ParametricProblem :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/problem/spatial_problem.rst b/docs/source/_rst/problem/spatial_problem.rst index 90ec6ec3c..757243ef1 100644 --- a/docs/source/_rst/problem/spatial_problem.rst +++ b/docs/source/_rst/problem/spatial_problem.rst @@ -2,8 +2,8 @@ SpatialProblem ============== .. currentmodule:: pina.problem.spatial_problem -.. automodule:: pina.problem.spatial_problem +.. automodule:: pina._src.problem.spatial_problem -.. autoclass:: SpatialProblem +.. autoclass:: pina._src.problem.spatial_problem.SpatialProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/time_dependent_problem.rst b/docs/source/_rst/problem/time_dependent_problem.rst index db94121c2..dda1e07f1 100644 --- a/docs/source/_rst/problem/time_dependent_problem.rst +++ b/docs/source/_rst/problem/time_dependent_problem.rst @@ -2,8 +2,8 @@ TimeDependentProblem ==================== .. currentmodule:: pina.problem.time_dependent_problem -.. automodule:: pina.problem.time_dependent_problem +.. automodule:: pina._src.problem.time_dependent_problem -.. autoclass:: TimeDependentProblem +.. autoclass:: pina._src.problem.time_dependent_problem.TimeDependentProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/acoustic_wave.rst b/docs/source/_rst/problem/zoo/acoustic_wave.rst index 4a9489667..34fd46895 100644 --- a/docs/source/_rst/problem/zoo/acoustic_wave.rst +++ b/docs/source/_rst/problem/zoo/acoustic_wave.rst @@ -2,8 +2,8 @@ AcousticWaveProblem ===================== .. currentmodule:: pina.problem.zoo.acoustic_wave -.. automodule:: pina.problem.zoo.acoustic_wave +.. automodule:: pina._src.problem.zoo.acoustic_wave -.. autoclass:: AcousticWaveProblem +.. autoclass:: pina._src.problem.zoo.acoustic_wave.AcousticWaveProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/advection.rst b/docs/source/_rst/problem/zoo/advection.rst index b83cc9d99..07d0cd45d 100644 --- a/docs/source/_rst/problem/zoo/advection.rst +++ b/docs/source/_rst/problem/zoo/advection.rst @@ -2,8 +2,8 @@ AdvectionProblem ================== .. currentmodule:: pina.problem.zoo.advection -.. automodule:: pina.problem.zoo.advection +.. automodule:: pina._src.problem.zoo.advection -.. autoclass:: AdvectionProblem +.. autoclass:: pina._src.problem.zoo.advection.AdvectionProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/allen_cahn.rst b/docs/source/_rst/problem/zoo/allen_cahn.rst index ada3465d1..7be2104bf 100644 --- a/docs/source/_rst/problem/zoo/allen_cahn.rst +++ b/docs/source/_rst/problem/zoo/allen_cahn.rst @@ -2,8 +2,8 @@ AllenCahnProblem ================== .. currentmodule:: pina.problem.zoo.allen_cahn -.. automodule:: pina.problem.zoo.allen_cahn +.. automodule:: pina._src.problem.zoo.allen_cahn -.. autoclass:: AllenCahnProblem +.. autoclass:: pina._src.problem.zoo.allen_cahn.AllenCahnProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/diffusion_reaction.rst b/docs/source/_rst/problem/zoo/diffusion_reaction.rst index 0cad0fd67..d5269edd7 100644 --- a/docs/source/_rst/problem/zoo/diffusion_reaction.rst +++ b/docs/source/_rst/problem/zoo/diffusion_reaction.rst @@ -2,8 +2,8 @@ DiffusionReactionProblem ========================= .. currentmodule:: pina.problem.zoo.diffusion_reaction -.. automodule:: pina.problem.zoo.diffusion_reaction +.. automodule:: pina._src.problem.zoo.diffusion_reaction -.. autoclass:: DiffusionReactionProblem +.. autoclass:: pina._src.problem.zoo.diffusion_reaction.DiffusionReactionProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/helmholtz.rst b/docs/source/_rst/problem/zoo/helmholtz.rst index af4ec7dbc..06724f83b 100644 --- a/docs/source/_rst/problem/zoo/helmholtz.rst +++ b/docs/source/_rst/problem/zoo/helmholtz.rst @@ -2,8 +2,8 @@ HelmholtzProblem ================== .. currentmodule:: pina.problem.zoo.helmholtz -.. automodule:: pina.problem.zoo.helmholtz +.. automodule:: pina._src.problem.zoo.helmholtz -.. autoclass:: HelmholtzProblem +.. autoclass:: pina._src.problem.zoo.helmholtz.HelmholtzProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/inverse_poisson_2d_square.rst b/docs/source/_rst/problem/zoo/inverse_poisson_2d_square.rst index 727c17b47..d4885ff0c 100644 --- a/docs/source/_rst/problem/zoo/inverse_poisson_2d_square.rst +++ b/docs/source/_rst/problem/zoo/inverse_poisson_2d_square.rst @@ -2,8 +2,8 @@ InversePoisson2DSquareProblem ============================== .. currentmodule:: pina.problem.zoo.inverse_poisson_2d_square -.. automodule:: pina.problem.zoo.inverse_poisson_2d_square +.. automodule:: pina._src.problem.zoo.inverse_poisson_2d_square -.. autoclass:: InversePoisson2DSquareProblem +.. autoclass:: pina._src.problem.zoo.inverse_poisson_2d_square.InversePoisson2DSquareProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/poisson_2d_square.rst b/docs/source/_rst/problem/zoo/poisson_2d_square.rst index 718c33ccc..96b5e4397 100644 --- a/docs/source/_rst/problem/zoo/poisson_2d_square.rst +++ b/docs/source/_rst/problem/zoo/poisson_2d_square.rst @@ -2,8 +2,8 @@ Poisson2DSquareProblem ======================== .. currentmodule:: pina.problem.zoo.poisson_2d_square -.. automodule:: pina.problem.zoo.poisson_2d_square +.. automodule:: pina._src.problem.zoo.poisson_2d_square -.. autoclass:: Poisson2DSquareProblem +.. autoclass:: pina._src.problem.zoo.poisson_2d_square.Poisson2DSquareProblem :members: :show-inheritance: diff --git a/docs/source/_rst/problem/zoo/supervised_problem.rst b/docs/source/_rst/problem/zoo/supervised_problem.rst index aad7d5aa5..6bf368376 100644 --- a/docs/source/_rst/problem/zoo/supervised_problem.rst +++ b/docs/source/_rst/problem/zoo/supervised_problem.rst @@ -2,8 +2,8 @@ SupervisedProblem ================== .. currentmodule:: pina.problem.zoo.supervised_problem -.. automodule:: pina.problem.zoo.supervised_problem +.. automodule:: pina._src.problem.zoo.supervised_problem -.. autoclass:: SupervisedProblem +.. autoclass:: pina._src.problem.zoo.supervised_problem.SupervisedProblem :members: :show-inheritance: diff --git a/docs/source/_rst/solver/ensemble_solver/ensemble_pinn.rst b/docs/source/_rst/solver/ensemble_solver/ensemble_pinn.rst index 2e42dcf0d..1ce086f45 100644 --- a/docs/source/_rst/solver/ensemble_solver/ensemble_pinn.rst +++ b/docs/source/_rst/solver/ensemble_solver/ensemble_pinn.rst @@ -2,7 +2,7 @@ DeepEnsemblePINN ================== .. currentmodule:: pina.solver.ensemble_solver.ensemble_pinn -.. autoclass:: DeepEnsemblePINN +.. autoclass:: pina._src.solver.ensemble_solver.ensemble_pinn.DeepEnsemblePINN :show-inheritance: :members: diff --git a/docs/source/_rst/solver/ensemble_solver/ensemble_solver_interface.rst b/docs/source/_rst/solver/ensemble_solver/ensemble_solver_interface.rst index 664bb8c8f..637520dd1 100644 --- a/docs/source/_rst/solver/ensemble_solver/ensemble_solver_interface.rst +++ b/docs/source/_rst/solver/ensemble_solver/ensemble_solver_interface.rst @@ -2,7 +2,7 @@ DeepEnsembleSolverInterface ============================= .. currentmodule:: pina.solver.ensemble_solver.ensemble_solver_interface -.. autoclass:: DeepEnsembleSolverInterface +.. autoclass:: pina._src.solver.ensemble_solver.ensemble_solver_interface.DeepEnsembleSolverInterface :show-inheritance: :members: diff --git a/docs/source/_rst/solver/ensemble_solver/ensemble_supervised.rst b/docs/source/_rst/solver/ensemble_solver/ensemble_supervised.rst index 575b28594..9b3f51522 100644 --- a/docs/source/_rst/solver/ensemble_solver/ensemble_supervised.rst +++ b/docs/source/_rst/solver/ensemble_solver/ensemble_supervised.rst @@ -2,7 +2,7 @@ DeepEnsembleSupervisedSolver ============================= .. currentmodule:: pina.solver.ensemble_solver.ensemble_supervised -.. autoclass:: DeepEnsembleSupervisedSolver +.. autoclass:: pina._src.solver.ensemble_solver.ensemble_supervised.DeepEnsembleSupervisedSolver :show-inheritance: :members: diff --git a/docs/source/_rst/solver/garom.rst b/docs/source/_rst/solver/garom.rst index 0e5820f6f..901272bee 100644 --- a/docs/source/_rst/solver/garom.rst +++ b/docs/source/_rst/solver/garom.rst @@ -2,6 +2,6 @@ GAROM ====== .. currentmodule:: pina.solver.garom -.. autoclass:: GAROM +.. autoclass:: pina._src.solver.garom.GAROM :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/multi_solver_interface.rst b/docs/source/_rst/solver/multi_solver_interface.rst index 7f68c83a4..676dffa5b 100644 --- a/docs/source/_rst/solver/multi_solver_interface.rst +++ b/docs/source/_rst/solver/multi_solver_interface.rst @@ -2,7 +2,7 @@ MultiSolverInterface ====================== .. currentmodule:: pina.solver.solver -.. autoclass:: MultiSolverInterface +.. autoclass:: pina._src.solver.solver.MultiSolverInterface :show-inheritance: :members: diff --git a/docs/source/_rst/solver/physics_informed_solver/causal_pinn.rst b/docs/source/_rst/solver/physics_informed_solver/causal_pinn.rst index 6fab9ef0e..2f6e2393c 100644 --- a/docs/source/_rst/solver/physics_informed_solver/causal_pinn.rst +++ b/docs/source/_rst/solver/physics_informed_solver/causal_pinn.rst @@ -2,6 +2,6 @@ CausalPINN ============== .. currentmodule:: pina.solver.physics_informed_solver.causal_pinn -.. autoclass:: CausalPINN +.. autoclass:: pina._src.solver.physics_informed_solver.causal_pinn.CausalPINN :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/physics_informed_solver/competitive_pinn.rst b/docs/source/_rst/solver/physics_informed_solver/competitive_pinn.rst index 372cb0f3d..3a48d280a 100644 --- a/docs/source/_rst/solver/physics_informed_solver/competitive_pinn.rst +++ b/docs/source/_rst/solver/physics_informed_solver/competitive_pinn.rst @@ -2,6 +2,6 @@ CompetitivePINN ================= .. currentmodule:: pina.solver.physics_informed_solver.competitive_pinn -.. autoclass:: CompetitivePINN +.. autoclass:: pina._src.solver.physics_informed_solver.competitive_pinn.CompetitivePINN :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/physics_informed_solver/gradient_pinn.rst b/docs/source/_rst/solver/physics_informed_solver/gradient_pinn.rst index 66a490013..7d5008cdb 100644 --- a/docs/source/_rst/solver/physics_informed_solver/gradient_pinn.rst +++ b/docs/source/_rst/solver/physics_informed_solver/gradient_pinn.rst @@ -2,6 +2,6 @@ GradientPINN ============== .. currentmodule:: pina.solver.physics_informed_solver.gradient_pinn -.. autoclass:: GradientPINN +.. autoclass:: pina._src.solver.physics_informed_solver.gradient_pinn.GradientPINN :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/physics_informed_solver/pinn.rst b/docs/source/_rst/solver/physics_informed_solver/pinn.rst index fdc31253b..48b9e603d 100644 --- a/docs/source/_rst/solver/physics_informed_solver/pinn.rst +++ b/docs/source/_rst/solver/physics_informed_solver/pinn.rst @@ -2,6 +2,6 @@ PINN ====== .. currentmodule:: pina.solver.physics_informed_solver.pinn -.. autoclass:: PINN +.. autoclass:: pina._src.solver.physics_informed_solver.pinn.PINN :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/physics_informed_solver/pinn_interface.rst b/docs/source/_rst/solver/physics_informed_solver/pinn_interface.rst index 2242cf8b4..6577d6e69 100644 --- a/docs/source/_rst/solver/physics_informed_solver/pinn_interface.rst +++ b/docs/source/_rst/solver/physics_informed_solver/pinn_interface.rst @@ -2,6 +2,6 @@ PINNInterface ================= .. currentmodule:: pina.solver.physics_informed_solver.pinn_interface -.. autoclass:: PINNInterface +.. autoclass:: pina._src.solver.physics_informed_solver.pinn_interface.PINNInterface :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/physics_informed_solver/rba_pinn.rst b/docs/source/_rst/solver/physics_informed_solver/rba_pinn.rst index cf94b6df0..af449fcf9 100644 --- a/docs/source/_rst/solver/physics_informed_solver/rba_pinn.rst +++ b/docs/source/_rst/solver/physics_informed_solver/rba_pinn.rst @@ -2,6 +2,6 @@ RBAPINN ======== .. currentmodule:: pina.solver.physics_informed_solver.rba_pinn -.. autoclass:: RBAPINN +.. autoclass:: pina._src.solver.physics_informed_solver.rba_pinn.RBAPINN :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/physics_informed_solver/self_adaptive_pinn.rst b/docs/source/_rst/solver/physics_informed_solver/self_adaptive_pinn.rst index 2290059bd..dc42385fe 100644 --- a/docs/source/_rst/solver/physics_informed_solver/self_adaptive_pinn.rst +++ b/docs/source/_rst/solver/physics_informed_solver/self_adaptive_pinn.rst @@ -2,6 +2,6 @@ SelfAdaptivePINN ================== .. currentmodule:: pina.solver.physics_informed_solver.self_adaptive_pinn -.. autoclass:: SelfAdaptivePINN +.. autoclass:: pina._src.solver.physics_informed_solver.self_adaptive_pinn.SelfAdaptivePINN :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/single_solver_interface.rst b/docs/source/_rst/solver/single_solver_interface.rst index 5b85f11b5..b47b85033 100644 --- a/docs/source/_rst/solver/single_solver_interface.rst +++ b/docs/source/_rst/solver/single_solver_interface.rst @@ -2,7 +2,7 @@ SingleSolverInterface ====================== .. currentmodule:: pina.solver.solver -.. autoclass:: SingleSolverInterface +.. autoclass:: pina._src.solver.solver.SingleSolverInterface :show-inheritance: :members: diff --git a/docs/source/_rst/solver/solver_interface.rst b/docs/source/_rst/solver/solver_interface.rst index 9bb11783e..bdd0aa92e 100644 --- a/docs/source/_rst/solver/solver_interface.rst +++ b/docs/source/_rst/solver/solver_interface.rst @@ -2,7 +2,7 @@ SolverInterface ================= .. currentmodule:: pina.solver.solver -.. autoclass:: SolverInterface +.. autoclass:: pina._src.solver.solver.SolverInterface :show-inheritance: :members: diff --git a/docs/source/_rst/solver/supervised_solver/reduced_order_model.rst b/docs/source/_rst/solver/supervised_solver/reduced_order_model.rst index 878014c29..08704c0b2 100644 --- a/docs/source/_rst/solver/supervised_solver/reduced_order_model.rst +++ b/docs/source/_rst/solver/supervised_solver/reduced_order_model.rst @@ -2,6 +2,6 @@ ReducedOrderModelSolver ========================== .. currentmodule:: pina.solver.supervised_solver.reduced_order_model -.. autoclass:: ReducedOrderModelSolver +.. autoclass:: pina._src.solver.supervised_solver.reduced_order_model.ReducedOrderModelSolver :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/supervised_solver/supervised.rst b/docs/source/_rst/solver/supervised_solver/supervised.rst index 60ffdf828..8c93c4400 100644 --- a/docs/source/_rst/solver/supervised_solver/supervised.rst +++ b/docs/source/_rst/solver/supervised_solver/supervised.rst @@ -2,6 +2,6 @@ SupervisedSolver =================== .. currentmodule:: pina.solver.supervised_solver.supervised -.. autoclass:: SupervisedSolver +.. autoclass:: pina._src.solver.supervised_solver.supervised.SupervisedSolver :members: :show-inheritance: \ No newline at end of file diff --git a/docs/source/_rst/solver/supervised_solver/supervised_solver_interface.rst b/docs/source/_rst/solver/supervised_solver/supervised_solver_interface.rst index 4903a18dd..565b977cc 100644 --- a/docs/source/_rst/solver/supervised_solver/supervised_solver_interface.rst +++ b/docs/source/_rst/solver/supervised_solver/supervised_solver_interface.rst @@ -2,7 +2,7 @@ SupervisedSolverInterface ========================== .. currentmodule:: pina.solver.supervised_solver.supervised_solver_interface -.. autoclass:: SupervisedSolverInterface +.. autoclass:: pina._src.solver.supervised_solver.supervised_solver_interface.SupervisedSolverInterface :show-inheritance: :members: diff --git a/docs/source/_rst/trainer.rst b/docs/source/_rst/trainer.rst index 2582b6da9..8e5a99a38 100644 --- a/docs/source/_rst/trainer.rst +++ b/docs/source/_rst/trainer.rst @@ -3,6 +3,6 @@ Trainer .. automodule:: pina.trainer -.. autoclass:: Trainer +.. autoclass:: pina._src.core.trainer.Trainer :members: :show-inheritance: \ No newline at end of file diff --git a/pina/__init__.py b/pina/__init__.py index 2cbe7f3bb..0d38804fe 100644 --- a/pina/__init__.py +++ b/pina/__init__.py @@ -1,8 +1,14 @@ -"""Module for the Pina library.""" +""" +PINA: Physics-Informed Neural Analysis. + +A specialized framework for Scientific Machine Learning (SciML), providing +tools for Physics-Informed Neural Networks (PINNs), Neural Operators, +and data-driven physical modeling. +""" __all__ = [ - "Trainer", "LabelTensor", + "Trainer", "Condition", "PinaDataModule", "Graph", @@ -10,9 +16,9 @@ "MultiSolverInterface", ] -from .label_tensor import LabelTensor -from .graph import Graph -from .solver import SolverInterface, MultiSolverInterface -from .trainer import Trainer -from .condition.condition import Condition -from .data import PinaDataModule +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.graph import Graph +from pina._src.solver.solver import SolverInterface, MultiSolverInterface +from pina._src.core.trainer import Trainer +from pina._src.condition.condition import Condition +from pina._src.data.data_module import PinaDataModule diff --git a/pina/_src/__init__.py b/pina/_src/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/_src/adaptive_function/__init__.py b/pina/_src/adaptive_function/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/adaptive_function/adaptive_function.py b/pina/_src/adaptive_function/adaptive_function.py similarity index 99% rename from pina/adaptive_function/adaptive_function.py rename to pina/_src/adaptive_function/adaptive_function.py index e6f86a549..21f45fd1e 100644 --- a/pina/adaptive_function/adaptive_function.py +++ b/pina/_src/adaptive_function/adaptive_function.py @@ -1,8 +1,10 @@ """Module for the Adaptive Functions.""" import torch -from ..utils import check_consistency -from .adaptive_function_interface import AdaptiveActivationFunctionInterface +from pina._src.core.utils import check_consistency +from pina._src.adaptive_function.adaptive_function_interface import ( + AdaptiveActivationFunctionInterface, +) class AdaptiveReLU(AdaptiveActivationFunctionInterface): diff --git a/pina/adaptive_function/adaptive_function_interface.py b/pina/_src/adaptive_function/adaptive_function_interface.py similarity index 98% rename from pina/adaptive_function/adaptive_function_interface.py rename to pina/_src/adaptive_function/adaptive_function_interface.py index a655fdbd7..d73382cb6 100644 --- a/pina/adaptive_function/adaptive_function_interface.py +++ b/pina/_src/adaptive_function/adaptive_function_interface.py @@ -2,7 +2,7 @@ from abc import ABCMeta import torch -from ..utils import check_consistency, is_function +from pina._src.core.utils import check_consistency, is_function class AdaptiveActivationFunctionInterface(torch.nn.Module, metaclass=ABCMeta): diff --git a/pina/_src/callback/__init__.py b/pina/_src/callback/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/_src/callback/optim/__init__.py b/pina/_src/callback/optim/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/callback/optim/switch_optimizer.py b/pina/_src/callback/optim/switch_optimizer.py similarity index 96% rename from pina/callback/optim/switch_optimizer.py rename to pina/_src/callback/optim/switch_optimizer.py index 3072b7c2e..4f6f0be09 100644 --- a/pina/callback/optim/switch_optimizer.py +++ b/pina/_src/callback/optim/switch_optimizer.py @@ -1,8 +1,8 @@ """Module for the SwitchOptimizer callback.""" from lightning.pytorch.callbacks import Callback -from ...optim import TorchOptimizer -from ...utils import check_consistency +from pina._src.optim.torch_optimizer import TorchOptimizer +from pina._src.core.utils import check_consistency class SwitchOptimizer(Callback): diff --git a/pina/callback/optim/switch_scheduler.py b/pina/_src/callback/optim/switch_scheduler.py similarity index 95% rename from pina/callback/optim/switch_scheduler.py rename to pina/_src/callback/optim/switch_scheduler.py index 3641f4ee4..bd4920bba 100644 --- a/pina/callback/optim/switch_scheduler.py +++ b/pina/_src/callback/optim/switch_scheduler.py @@ -1,8 +1,8 @@ """Module for the SwitchScheduler callback.""" from lightning.pytorch.callbacks import Callback -from ...optim import TorchScheduler -from ...utils import check_consistency, check_positive_integer +from pina._src.optim.torch_scheduler import TorchScheduler +from pina._src.core.utils import check_consistency, check_positive_integer class SwitchScheduler(Callback): diff --git a/pina/_src/callback/processing/__init__.py b/pina/_src/callback/processing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/callback/processing/metric_tracker.py b/pina/_src/callback/processing/metric_tracker.py similarity index 100% rename from pina/callback/processing/metric_tracker.py rename to pina/_src/callback/processing/metric_tracker.py diff --git a/pina/callback/processing/normalizer_data_callback.py b/pina/_src/callback/processing/normalizer_data_callback.py similarity index 97% rename from pina/callback/processing/normalizer_data_callback.py rename to pina/_src/callback/processing/normalizer_data_callback.py index 4d85a7d9a..2524f5765 100644 --- a/pina/callback/processing/normalizer_data_callback.py +++ b/pina/_src/callback/processing/normalizer_data_callback.py @@ -2,10 +2,10 @@ import torch from lightning.pytorch import Callback -from ...label_tensor import LabelTensor -from ...utils import check_consistency, is_function -from ...condition import InputTargetCondition -from ...data.dataset import PinaGraphDataset +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency, is_function +from pina._src.condition.condition import InputTargetCondition +from pina._src.data.dataset import PinaGraphDataset class NormalizerDataCallback(Callback): diff --git a/pina/callback/processing/pina_progress_bar.py b/pina/_src/callback/processing/pina_progress_bar.py similarity index 98% rename from pina/callback/processing/pina_progress_bar.py rename to pina/_src/callback/processing/pina_progress_bar.py index 4c322a5e8..90c34f8cc 100644 --- a/pina/callback/processing/pina_progress_bar.py +++ b/pina/_src/callback/processing/pina_progress_bar.py @@ -4,7 +4,7 @@ from lightning.pytorch.callbacks.progress.progress_bar import ( get_standard_metrics, ) -from pina.utils import check_consistency +from pina._src.core.utils import check_consistency class PINAProgressBar(TQDMProgressBar): diff --git a/pina/_src/callback/refinement/__init__.py b/pina/_src/callback/refinement/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/callback/refinement/r3_refinement.py b/pina/_src/callback/refinement/r3_refinement.py similarity index 93% rename from pina/callback/refinement/r3_refinement.py rename to pina/_src/callback/refinement/r3_refinement.py index 863dedfc1..b8bcc7285 100644 --- a/pina/callback/refinement/r3_refinement.py +++ b/pina/_src/callback/refinement/r3_refinement.py @@ -1,10 +1,12 @@ """Module for the R3Refinement callback.""" import torch -from .refinement_interface import RefinementInterface -from ...label_tensor import LabelTensor -from ...utils import check_consistency -from ...loss import LossInterface +from pina._src.callback.refinement.refinement_interface import ( + RefinementInterface, +) +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency +from pina._src.loss.loss_interface import LossInterface class R3Refinement(RefinementInterface): diff --git a/pina/callback/refinement/refinement_interface.py b/pina/_src/callback/refinement/refinement_interface.py similarity index 97% rename from pina/callback/refinement/refinement_interface.py rename to pina/_src/callback/refinement/refinement_interface.py index adc6e4e7c..83ca8d8be 100644 --- a/pina/callback/refinement/refinement_interface.py +++ b/pina/_src/callback/refinement/refinement_interface.py @@ -5,8 +5,10 @@ from abc import ABCMeta, abstractmethod from lightning.pytorch import Callback -from ...utils import check_consistency -from ...solver.physics_informed_solver import PINNInterface +from pina._src.core.utils import check_consistency +from pina._src.solver.physics_informed_solver.pinn_interface import ( + PINNInterface, +) class RefinementInterface(Callback, metaclass=ABCMeta): diff --git a/pina/_src/condition/__init__.py b/pina/_src/condition/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/condition/condition.py b/pina/_src/condition/condition.py similarity index 95% rename from pina/condition/condition.py rename to pina/_src/condition/condition.py index ad8764c9f..db2a666d8 100644 --- a/pina/condition/condition.py +++ b/pina/_src/condition/condition.py @@ -1,9 +1,11 @@ """Module for the Condition class.""" -from .data_condition import DataCondition -from .domain_equation_condition import DomainEquationCondition -from .input_equation_condition import InputEquationCondition -from .input_target_condition import InputTargetCondition +from pina._src.condition.data_condition import DataCondition +from pina._src.condition.domain_equation_condition import ( + DomainEquationCondition, +) +from pina._src.condition.input_equation_condition import InputEquationCondition +from pina._src.condition.input_target_condition import InputTargetCondition class Condition: diff --git a/pina/condition/condition_interface.py b/pina/_src/condition/condition_interface.py similarity index 98% rename from pina/condition/condition_interface.py rename to pina/_src/condition/condition_interface.py index b0264517c..509ac2fc3 100644 --- a/pina/condition/condition_interface.py +++ b/pina/_src/condition/condition_interface.py @@ -2,8 +2,8 @@ from abc import ABCMeta from torch_geometric.data import Data -from ..label_tensor import LabelTensor -from ..graph import Graph +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.graph import Graph class ConditionInterface(metaclass=ABCMeta): diff --git a/pina/condition/data_condition.py b/pina/_src/condition/data_condition.py similarity index 96% rename from pina/condition/data_condition.py rename to pina/_src/condition/data_condition.py index 5f5e7d36b..ec6da762c 100644 --- a/pina/condition/data_condition.py +++ b/pina/_src/condition/data_condition.py @@ -2,9 +2,9 @@ import torch from torch_geometric.data import Data -from .condition_interface import ConditionInterface -from ..label_tensor import LabelTensor -from ..graph import Graph +from pina._src.condition.condition_interface import ConditionInterface +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.graph import Graph class DataCondition(ConditionInterface): diff --git a/pina/condition/domain_equation_condition.py b/pina/_src/condition/domain_equation_condition.py similarity index 89% rename from pina/condition/domain_equation_condition.py rename to pina/_src/condition/domain_equation_condition.py index 3565c0b41..0b75269ce 100644 --- a/pina/condition/domain_equation_condition.py +++ b/pina/_src/condition/domain_equation_condition.py @@ -1,9 +1,9 @@ """Module for the DomainEquationCondition class.""" -from .condition_interface import ConditionInterface -from ..utils import check_consistency -from ..domain import DomainInterface -from ..equation.equation_interface import EquationInterface +from pina._src.condition.condition_interface import ConditionInterface +from pina._src.core.utils import check_consistency +from pina._src.domain.domain_interface import DomainInterface +from pina._src.equation.equation_interface import EquationInterface class DomainEquationCondition(ConditionInterface): diff --git a/pina/condition/input_equation_condition.py b/pina/_src/condition/input_equation_condition.py similarity index 95% rename from pina/condition/input_equation_condition.py rename to pina/_src/condition/input_equation_condition.py index d32597894..636d8b9f8 100644 --- a/pina/condition/input_equation_condition.py +++ b/pina/_src/condition/input_equation_condition.py @@ -1,10 +1,10 @@ """Module for the InputEquationCondition class and its subclasses.""" -from .condition_interface import ConditionInterface -from ..label_tensor import LabelTensor -from ..graph import Graph -from ..utils import check_consistency -from ..equation.equation_interface import EquationInterface +from pina._src.condition.condition_interface import ConditionInterface +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.graph import Graph +from pina._src.core.utils import check_consistency +from pina._src.equation.equation_interface import EquationInterface class InputEquationCondition(ConditionInterface): diff --git a/pina/condition/input_target_condition.py b/pina/_src/condition/input_target_condition.py similarity index 98% rename from pina/condition/input_target_condition.py rename to pina/_src/condition/input_target_condition.py index 07b07bb7b..e1392ed75 100644 --- a/pina/condition/input_target_condition.py +++ b/pina/_src/condition/input_target_condition.py @@ -4,9 +4,9 @@ import torch from torch_geometric.data import Data -from ..label_tensor import LabelTensor -from ..graph import Graph -from .condition_interface import ConditionInterface +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.graph import Graph +from pina._src.condition.condition_interface import ConditionInterface class InputTargetCondition(ConditionInterface): diff --git a/pina/_src/core/__init__.py b/pina/_src/core/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/_src/core/graph.py b/pina/_src/core/graph.py new file mode 100644 index 000000000..3c72051ec --- /dev/null +++ b/pina/_src/core/graph.py @@ -0,0 +1,421 @@ +"""Module to build Graph objects and perform operations on them.""" + +import torch +from torch_geometric.data import Data, Batch +from torch_geometric.utils import to_undirected +from torch_geometric.utils.loop import remove_self_loops +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency, is_function + + +class Graph(Data): + """ + Extends :class:`~torch_geometric.data.Data` class to include additional + checks and functionalities. + """ + + def __new__( + cls, + **kwargs, + ): + """ + Create a new instance of the :class:`~pina.graph.Graph` class by + checking the consistency of the input data and storing the attributes. + + :param dict kwargs: Parameters used to initialize the + :class:`~pina.graph.Graph` object. + :return: A new instance of the :class:`~pina.graph.Graph` class. + :rtype: Graph + """ + # create class instance + instance = Data.__new__(cls) + + # check the consistency of types defined in __init__, the others are not + # checked (as in pyg Data object) + instance._check_type_consistency(**kwargs) + + return instance + + def __init__( + self, + x=None, + edge_index=None, + pos=None, + edge_attr=None, + undirected=False, + **kwargs, + ): + """ + Initialize the object by setting the node features, edge index, + edge attributes, and positions. The edge index is preprocessed to make + the graph undirected if required. For more details, see the + :meth:`torch_geometric.data.Data` + + :param x: Optional tensor of node features ``(N, F)`` where ``F`` is the + number of features per node. + :type x: torch.Tensor, LabelTensor + :param torch.Tensor edge_index: A tensor of shape ``(2, E)`` + representing the indices of the graph's edges. + :param pos: A tensor of shape ``(N, D)`` representing the positions of + ``N`` points in ``D``-dimensional space. + :type pos: torch.Tensor | LabelTensor + :param edge_attr: Optional tensor of edge_featured ``(E, F')`` where + ``F'`` is the number of edge features + :type edge_attr: torch.Tensor | LabelTensor + :param bool undirected: Whether to make the graph undirected + :param dict kwargs: Additional keyword arguments passed to the + :class:`~torch_geometric.data.Data` class constructor. + """ + # preprocessing + self._preprocess_edge_index(edge_index, undirected) + + # calling init + super().__init__( + x=x, edge_index=edge_index, edge_attr=edge_attr, pos=pos, **kwargs + ) + + def _check_type_consistency(self, **kwargs): + """ + Check the consistency of the types of the input data. + + :param dict kwargs: Attributes to be checked for consistency. + """ + # default types, specified in cls.__new__, by default they are Nont + # if specified in **kwargs they get override + x, pos, edge_index, edge_attr = None, None, None, None + if "pos" in kwargs: + pos = kwargs["pos"] + self._check_pos_consistency(pos) + if "edge_index" in kwargs: + edge_index = kwargs["edge_index"] + self._check_edge_index_consistency(edge_index) + if "x" in kwargs: + x = kwargs["x"] + self._check_x_consistency(x, pos) + if "edge_attr" in kwargs: + edge_attr = kwargs["edge_attr"] + self._check_edge_attr_consistency(edge_attr, edge_index) + if "undirected" in kwargs: + undirected = kwargs["undirected"] + check_consistency(undirected, bool) + + @staticmethod + def _check_pos_consistency(pos): + """ + Check if the position tensor is consistent. + :param torch.Tensor pos: The position tensor. + :raises ValueError: If the position tensor is not consistent. + """ + if pos is not None: + check_consistency(pos, (torch.Tensor, LabelTensor)) + if pos.ndim != 2: + raise ValueError("pos must be a 2D tensor.") + + @staticmethod + def _check_edge_index_consistency(edge_index): + """ + Check if the edge index is consistent. + + :param torch.Tensor edge_index: The edge index tensor. + :raises ValueError: If the edge index tensor is not consistent. + """ + check_consistency(edge_index, (torch.Tensor, LabelTensor)) + if edge_index.ndim != 2: + raise ValueError("edge_index must be a 2D tensor.") + if edge_index.size(0) != 2: + raise ValueError("edge_index must have shape [2, num_edges].") + + @staticmethod + def _check_edge_attr_consistency(edge_attr, edge_index): + """ + Check if the edge attribute tensor is consistent in type and shape + with the edge index. + + :param edge_attr: The edge attribute tensor. + :type edge_attr: torch.Tensor | LabelTensor + :param torch.Tensor edge_index: The edge index tensor. + :raises ValueError: If the edge attribute tensor is not consistent. + """ + if edge_attr is not None: + check_consistency(edge_attr, (torch.Tensor, LabelTensor)) + if edge_attr.ndim != 2: + raise ValueError("edge_attr must be a 2D tensor.") + if edge_attr.size(0) != edge_index.size(1): + raise ValueError( + "edge_attr must have shape " + "[num_edges, num_edge_features], expected " + f"num_edges {edge_index.size(1)} " + f"got {edge_attr.size(0)}." + ) + + @staticmethod + def _check_x_consistency(x, pos=None): + """ + Check if the input tensor x is consistent with the position tensor + `pos`. + + :param x: The input tensor. + :type x: torch.Tensor | LabelTensor + :param pos: The position tensor. + :type pos: torch.Tensor | LabelTensor + :raises ValueError: If the input tensor is not consistent. + """ + if x is not None: + check_consistency(x, (torch.Tensor, LabelTensor)) + if x.ndim != 2: + raise ValueError("x must be a 2D tensor.") + if pos is not None: + if x.size(0) != pos.size(0): + raise ValueError("Inconsistent number of nodes.") + + @staticmethod + def _preprocess_edge_index(edge_index, undirected): + """ + Preprocess the edge index to make the graph undirected (if required). + + :param torch.Tensor edge_index: The edge index. + :param bool undirected: Whether the graph is undirected. + :return: The preprocessed edge index. + :rtype: torch.Tensor + """ + if undirected: + edge_index = to_undirected(edge_index) + return edge_index + + def extract(self, labels, attr="x"): + """ + Perform extraction of labels from the attribute specified by `attr`. + + :param labels: Labels to extract + :type labels: list[str] | tuple[str] | str | dict + :return: Batch object with extraction performed on x + :rtype: PinaBatch + """ + # Extract labels from LabelTensor object + tensor = getattr(self, attr).extract(labels) + # Set the extracted tensor as the new attribute + setattr(self, attr, tensor) + return self + + +class GraphBuilder: + """ + A class that allows an easy definition of :class:`Graph` instances. + """ + + def __new__( + cls, + pos, + edge_index, + x=None, + edge_attr=False, + custom_edge_func=None, + loop=True, + **kwargs, + ): + """ + Compute the edge attributes and create a new instance of the + :class:`~pina.graph.Graph` class. + + :param pos: A tensor of shape ``(N, D)`` representing the positions of + ``N`` points in ``D``-dimensional space. + :type pos: torch.Tensor or LabelTensor + :param edge_index: A tensor of shape ``(2, E)`` representing the indices + of the graph's edges. + :type edge_index: torch.Tensor + :param x: Optional tensor of node features of shape ``(N, F)``, where + ``F`` is the number of features per node. + :type x: torch.Tensor | LabelTensor, optional + :param bool edge_attr: Whether to compute the edge attributes. + :param custom_edge_func: A custom function to compute edge attributes. + If provided, overrides ``edge_attr``. + :type custom_edge_func: Callable, optional + :param bool loop: Whether to include self-loops. + :param kwargs: Additional keyword arguments passed to the + :class:`~pina.graph.Graph` class constructor. + :return: A :class:`~pina.graph.Graph` instance constructed using the + provided information. + :rtype: Graph + """ + if not loop: + edge_index = remove_self_loops(edge_index)[0] + edge_attr = cls._create_edge_attr( + pos, edge_index, edge_attr, custom_edge_func or cls._build_edge_attr + ) + return Graph( + x=x, + edge_index=edge_index, + edge_attr=edge_attr, + pos=pos, + **kwargs, + ) + + @staticmethod + def _create_edge_attr(pos, edge_index, edge_attr, func): + """ + Create the edge attributes based on the input parameters. + + :param pos: Positions of the points. + :type pos: torch.Tensor | LabelTensor + :param torch.Tensor edge_index: Edge indices. + :param bool edge_attr: Whether to compute the edge attributes. + :param Callable func: Function to compute the edge attributes. + :raises ValueError: If ``func`` is not a function. + :return: The edge attributes. + :rtype: torch.Tensor | LabelTensor | None + """ + check_consistency(edge_attr, bool) + if edge_attr: + if is_function(func): + return func(pos, edge_index) + raise ValueError("custom_edge_func must be a function.") + return None + + @staticmethod + def _build_edge_attr(pos, edge_index): + """ + Default function to compute the edge attributes. + + :param pos: Positions of the points. + :type pos: torch.Tensor | LabelTensor + :param torch.Tensor edge_index: Edge indices. + :return: The edge attributes. + :rtype: torch.Tensor + """ + return ( + (pos[edge_index[0]] - pos[edge_index[1]]) + .abs() + .as_subclass(torch.Tensor) + ) + + +class RadiusGraph(GraphBuilder): + """ + Extends the :class:`~pina.graph.GraphBuilder` class to compute + ``edge_index`` based on a radius. Each point is connected to all the points + within the radius. + """ + + def __new__(cls, pos, radius, **kwargs): + """ + Instantiate the :class:`~pina.graph.Graph` class by computing the + ``edge_index`` based on the radius provided. + + :param pos: A tensor of shape ``(N, D)`` representing the positions of + ``N`` points in ``D``-dimensional space. + :type pos: torch.Tensor | LabelTensor + :param float radius: The radius within which points are connected. + :param dict kwargs: The additional keyword arguments to be passed to + :class:`GraphBuilder` and :class:`Graph` classes. + :return: A :class:`~pina.graph.Graph` instance with the computed + ``edge_index``. + :rtype: Graph + """ + edge_index = cls.compute_radius_graph(pos, radius) + return super().__new__(cls, pos=pos, edge_index=edge_index, **kwargs) + + @staticmethod + def compute_radius_graph(points, radius): + """ + Computes the ``edge_index`` based on the radius. Each point is connected + to all the points within the radius. + + :param points: A tensor of shape ``(N, D)`` representing the positions + of ``N`` points in ``D``-dimensional space. + :type points: torch.Tensor | LabelTensor + :param float radius: The radius within which points are connected. + :return: A tensor of shape ``(2, E)``, with ``E`` number of edges, + representing the edge indices of the graph. + :rtype: torch.Tensor + """ + dist = torch.cdist(points, points, p=2) + return ( + torch.nonzero(dist <= radius, as_tuple=False) + .t() + .as_subclass(torch.Tensor) + ) + + +class KNNGraph(GraphBuilder): + """ + Extends the :class:`~pina.graph.GraphBuilder` class to compute + ``edge_index`` based on a K-nearest neighbors algorithm. + """ + + def __new__(cls, pos, neighbours, **kwargs): + """ + Instantiate the :class:`~pina.graph.Graph` class by computing the + ``edge_index`` based on the K-nearest neighbors algorithm. + + :param pos: A tensor of shape ``(N, D)`` representing the positions of + ``N`` points in ``D``-dimensional space. + :type pos: torch.Tensor | LabelTensor + :param int neighbours: The number of nearest neighbors to consider when + building the graph. + :param dict kwargs: The additional keyword arguments to be passed to + :class:`GraphBuilder` and :class:`Graph` classes. + + :return: A :class:`~pina.graph.Graph` instance with the computed + ``edge_index``. + :rtype: Graph + """ + + edge_index = cls.compute_knn_graph(pos, neighbours) + return super().__new__(cls, pos=pos, edge_index=edge_index, **kwargs) + + @staticmethod + def compute_knn_graph(points, neighbours): + """ + Computes the ``edge_index`` based on the K-nearest neighbors algorithm. + + :param points: A tensor of shape ``(N, D)`` representing the positions + of ``N`` points in ``D``-dimensional space. + :type points: torch.Tensor | LabelTensor + :param int neighbours: The number of nearest neighbors to consider when + building the graph. + :return: A tensor of shape ``(2, E)``, with ``E`` number of edges, + representing the edge indices of the graph. + :rtype: torch.Tensor + """ + dist = torch.cdist(points, points, p=2) + knn_indices = torch.topk(dist, k=neighbours, largest=False).indices + row = torch.arange(points.size(0)).repeat_interleave(neighbours) + col = knn_indices.flatten() + return torch.stack([row, col], dim=0).as_subclass(torch.Tensor) + + +class LabelBatch(Batch): + """ + Extends the :class:`~torch_geometric.data.Batch` class to include + :class:`~pina.label_tensor.LabelTensor` objects. + """ + + @classmethod + def from_data_list(cls, data_list): + """ + Create a Batch object from a list of :class:`~torch_geometric.data.Data` + or :class:`~pina.graph.Graph` objects. + + :param data_list: List of :class:`~torch_geometric.data.Data` or + :class:`~pina.graph.Graph` objects. + :type data_list: list[Data] | list[Graph] + :return: A :class:`~torch_geometric.data.Batch` object containing + the input data. + :rtype: :class:`~torch_geometric.data.Batch` + """ + # Store the labels of Data/Graph objects (all data have the same labels) + # If the data do not contain labels, labels is an empty dictionary, + # therefore the labels are not stored + labels = { + k: v.labels + for k, v in data_list[0].items() + if isinstance(v, LabelTensor) + } + + # Create a Batch object from the list of Data objects + batch = super().from_data_list(data_list) + + # Put the labels back in the Batch object + for k, v in labels.items(): + batch[k].labels = v + return batch diff --git a/pina/_src/core/label_tensor.py b/pina/_src/core/label_tensor.py new file mode 100644 index 000000000..41bccc6fc --- /dev/null +++ b/pina/_src/core/label_tensor.py @@ -0,0 +1,753 @@ +"""Module for LabelTensor""" + +from copy import copy, deepcopy +import torch +from torch import Tensor + + +class LabelTensor(torch.Tensor): + """ + Extension of the :class:`torch.Tensor` class that includes labels for + each dimension. + """ + + @staticmethod + def __new__(cls, x, labels, *args, **kwargs): + """ + Create a new instance of the :class:`~pina.label_tensor.LabelTensor` + class. + + :param torch.Tensor x: :class:`torch.tensor` instance to be casted as a + :class:`~pina.label_tensor.LabelTensor`. + :param labels: Labels to assign to the tensor. + :type labels: str | list[str] | dict + :return: The instance of the :class:`~pina.label_tensor.LabelTensor` + class. + :rtype: LabelTensor + """ + + if isinstance(x, LabelTensor): + return x + return super().__new__(cls, x, *args, **kwargs) + + @property + def tensor(self): + """ + Returns the tensor part of the :class:`~pina.label_tensor.LabelTensor` + object. + + :return: Tensor part of the :class:`~pina.label_tensor.LabelTensor`. + :rtype: torch.Tensor + """ + + return self.as_subclass(Tensor) + + def __init__(self, x, labels): + """ + Initialize the :class:`~pina.label_tensor.LabelTensor` instance, by + checking the consistency of the labels and the tensor. Specifically, the + labels must match the following conditions: + + - At each dimension, the number of labels must match the size of the \ + dimension. + - At each dimension, the labels must be unique. + + The labels can be passed in the following formats: + + :Example: + >>> from pina import LabelTensor + >>> tensor = LabelTensor( + >>> torch.rand((2000, 3)), + ... {1: {"name": "space", "dof": ['a', 'b', 'c']}}) + >>> tensor = LabelTensor( + >>> torch.rand((2000, 3)), + ... ["a", "b", "c"]) + + The keys of the dictionary are the dimension indices, and the values are + dictionaries containing the labels and the name of the dimension. If + the labels are passed as a list, these are assigned to the last + dimension. + + :param torch.Tensor x: The tensor to be casted as a + :class:`~pina.label_tensor.LabelTensor`. + :param labels: Labels to assign to the tensor. + :type labels: str | list[str] | dict + :raises ValueError: If the labels are not consistent with the tensor. + """ + super().__init__() + if labels is not None: + self.labels = labels + else: + self._labels = {} + + @property + def full_labels(self): + """ + Returns the full labels of the tensor, even for the dimensions that are + not labeled. + + :return: The full labels of the tensor + :rtype: dict + """ + to_return_dict = {} + shape_tensor = self.shape + for i, value in enumerate(shape_tensor): + if i in self._labels: + to_return_dict[i] = self._labels[i] + else: + to_return_dict[i] = {"dof": range(value), "name": i} + return to_return_dict + + @property + def stored_labels(self): + """ + Returns the labels stored inside the instance. + + :return: The labels stored inside the instance. + :rtype: dict + """ + return self._labels + + @property + def labels(self): + """ + Returns the labels of the last dimension of the instance. + + :return: labels of last dimension + :rtype: list + """ + if self.ndim - 1 in self._labels: + return self._labels[self.ndim - 1]["dof"] + return None + + @labels.setter + def labels(self, labels): + """ + Set labels stored insider the instance by checking the type of the + input labels and handling it accordingly. The following types are + accepted: + + - **list**: The list of labels is assigned to the last dimension. + - **dict**: The dictionary of labels is assigned to the tensor. + - **str**: The string is assigned to the last dimension. + + :param labels: Labels to assign to the class variable _labels. + :type labels: str | list[str] | dict + """ + + if not hasattr(self, "_labels"): + self._labels = {} + if isinstance(labels, dict): + self._init_labels_from_dict(labels) + elif isinstance(labels, (list, range)): + self._init_labels_from_list(labels) + elif isinstance(labels, str): + labels = [labels] + self._init_labels_from_list(labels) + else: + raise ValueError("labels must be list, dict or string.") + + def _init_labels_from_dict(self, labels): + """ + Store the internal label representation according to the values + passed as input. + + :param dict labels: The label(s) to update. + :raises ValueError: If the dof list contains duplicates or the number of + dof does not match the tensor shape. + """ + + tensor_shape = self.shape + + def validate_dof(dof_list, dim_size): + """Validate the 'dof' list for uniqueness and size.""" + if len(dof_list) != len(set(dof_list)): + raise ValueError("dof must be unique") + if len(dof_list) != dim_size: + raise ValueError( + f"Number of dof ({len(dof_list)}) does not match " + f"tensor shape ({dim_size})" + ) + + for dim, label in labels.items(): + if isinstance(label, dict): + if "name" not in label: + label["name"] = dim + if "dof" not in label: + label["dof"] = range(tensor_shape[dim]) + if "dof" in label and "name" in label: + dof = label["dof"] + dof_list = dof if isinstance(dof, (list, range)) else [dof] + if not isinstance(dof_list, (list, range)): + raise ValueError( + f"'dof' should be a list or range, not" + f" {type(dof_list)}" + ) + validate_dof(dof_list, tensor_shape[dim]) + else: + raise ValueError( + "Labels dictionary must contain either " + " both 'name' and 'dof' keys" + ) + else: + raise ValueError( + f"Invalid label format for {dim}: Expected " + f"list or dictionary, got {type(label)}" + ) + + # Assign validated label data to internal labels + self._labels[dim] = label + + def _init_labels_from_list(self, labels): + """ + Given a list of dof, this method update the internal label + representation by assigning the dof to the last dimension. + + :param labels: The label(s) to update. + :type labels: list + """ + + # Create a dict with labels + last_dim_labels = { + self.ndim - 1: {"dof": labels, "name": self.ndim - 1} + } + self._init_labels_from_dict(last_dim_labels) + + def extract(self, labels_to_extract): + """ + Extract the subset of the original tensor by returning all the positions + corresponding to the passed ``label_to_extract``. If + ``label_to_extract`` is a dictionary, the keys are the dimension names + and the values are the labels to extract. If a single label or a list + of labels is passed, the last dimension is considered. + + :Example: + >>> from pina import LabelTensor + >>> labels = {1: {'dof': ["a", "b", "c"], 'name': 'space'}} + >>> tensor = LabelTensor(torch.rand((2000, 3)), labels) + >>> tensor.extract("a") + >>> tensor.extract(["a", "b"]) + >>> tensor.extract({"space": ["a", "b"]}) + + :param labels_to_extract: The label(s) to extract. + :type labels_to_extract: str | list[str] | tuple[str] | dict + :return: The extracted tensor with the updated labels. + :rtype: LabelTensor + + :raises TypeError: Labels are not ``str``, ``list[str]`` or ``dict`` + properly setted. + :raises ValueError: Label to extract is not in the labels ``list``. + """ + + def get_label_indices(dim_labels, labels_te): + if isinstance(labels_te, (int, str)): + labels_te = [labels_te] + return ( + [dim_labels.index(label) for label in labels_te] + if len(labels_te) > 1 + else slice( + dim_labels.index(labels_te[0]), + dim_labels.index(labels_te[0]) + 1, + ) + ) + + # Ensure labels_to_extract is a list or dict + if isinstance(labels_to_extract, (str, int)): + labels_to_extract = [labels_to_extract] + + labels = copy(self._labels) + + # Get the dimension names and the respective dimension index + dim_names = {labels[dim]["name"]: dim for dim in labels} + ndim = super().ndim + tensor = self.tensor.as_subclass(torch.Tensor) + + # Convert list/tuple to a dict for the last dimension if applicable + if isinstance(labels_to_extract, (list, tuple)): + last_dim = ndim - 1 + dim_name = labels[last_dim]["name"] + labels_to_extract = {dim_name: list(labels_to_extract)} + + # Validate the labels_to_extract type + if not isinstance(labels_to_extract, dict): + raise ValueError( + "labels_to_extract must be a string, list, or dictionary." + ) + + # Perform the extraction for each specified dimension + for dim_name, labels_te in labels_to_extract.items(): + if dim_name not in dim_names: + raise ValueError( + f"Cannot extract labels for dimension '{dim_name}' as it is" + f" not present in the original labels." + ) + + idx_dim = dim_names[dim_name] + dim_labels = labels[idx_dim]["dof"] + indices = get_label_indices(dim_labels, labels_te) + + extractor = [slice(None)] * ndim + extractor[idx_dim] = indices + tensor = tensor[tuple(extractor)] + + labels[idx_dim] = {"dof": labels_te, "name": dim_name} + + return LabelTensor(tensor, labels) + + def __str__(self): + """ + The string representation of the + :class:`~pina.label_tensor.LabelTensor`. + + :return: String representation of the + :class:`~pina.label_tensor.LabelTensor` instance. + :rtype: str + """ + + s = "" + for key, value in self._labels.items(): + s += f"{key}: {value}\n" + s += "\n" + s += self.tensor.__str__() + return s + + @staticmethod + def cat(tensors, dim=0): + """ + Concatenate a list of tensors along a specified dimension. For more + details, see :meth:`torch.cat`. + + :param list[LabelTensor] tensors: + :class:`~pina.label_tensor.LabelTensor` instances to concatenate + :param int dim: Dimensions on which you want to perform the operation + (default is 0) + :return: A new :class:`LabelTensor` instance obtained by concatenating + the input instances. + + :rtype: LabelTensor + :raises ValueError: either number dof or dimensions names differ. + """ + + if not tensors: + return [] # Handle empty list + if len(tensors) == 1: + return tensors[0] # Return single tensor as-is + + # Perform concatenation + cat_tensor = torch.cat(tensors, dim=dim) + tensors_labels = [tensor.stored_labels for tensor in tensors] + + # Check label consistency across tensors, excluding the + # concatenation dimension + for key in tensors_labels[0]: + if key != dim: + if any( + tensors_labels[i][key] != tensors_labels[0][key] + for i in range(len(tensors_labels)) + ): + raise RuntimeError( + f"Tensors must have the same labels along all " + f"dimensions except {dim}." + ) + + # Copy and update the 'dof' for the concatenation dimension + cat_labels = {k: copy(v) for k, v in tensors_labels[0].items()} + + # Update labels if the concatenation dimension has labels + if dim in tensors[0].stored_labels: + if dim in cat_labels: + cat_dofs = [label[dim]["dof"] for label in tensors_labels] + cat_labels[dim]["dof"] = sum(cat_dofs, []) + else: + cat_labels = tensors[0].stored_labels + + # Assign updated labels to the concatenated tensor + cat_tensor._labels = cat_labels + return cat_tensor + + @staticmethod + def stack(tensors): + """ + Stacks a list of tensors along a new dimension. For more details, see + :meth:`torch.stack`. + + :param list[LabelTensor] tensors: A list of tensors to stack. + All tensors must have the same shape. + :return: A new :class:`~pina.label_tensor.LabelTensor` instance obtained + by stacking the input tensors. + :rtype: LabelTensor + """ + + # Perform stacking in torch + new_tensor = torch.stack(tensors) + + # Increase labels keys by 1 + labels = tensors[0]._labels + labels = {key + 1: value for key, value in labels.items()} + new_tensor._labels = labels + return new_tensor + + def requires_grad_(self, mode=True): + """ + Override the :meth:`~torch.Tensor.requires_grad_` method to handle + the labels in the new tensor. + For more details, see :meth:`~torch.Tensor.requires_grad_`. + + :param bool mode: A boolean value indicating whether the tensor should + track gradients.If `True`, the tensor will track gradients; + if `False`, it will not. + :return: The :class:`~pina.label_tensor.LabelTensor` itself with the + updated ``requires_grad`` state and retained labels. + :rtype: LabelTensor + """ + + lt = super().requires_grad_(mode) + lt._labels = self._labels + return lt + + @property + def dtype(self): + """ + Give the ``dtype`` of the tensor. For more details, see + :meth:`torch.dtype`. + + :return: The data type of the tensor. + :rtype: torch.dtype + """ + + return super().dtype + + def to(self, *args, **kwargs): + """ + Performs Tensor dtype and/or device conversion. For more details, see + :meth:`torch.Tensor.to`. + + :return: A new :class:`~pina.label_tensor.LabelTensor` instance with the + updated dtype and/or device and retained labels. + :rtype: LabelTensor + """ + + lt = super().to(*args, **kwargs) + lt._labels = self._labels + return lt + + def clone(self, *args, **kwargs): + """ + Clone the :class:`~pina.label_tensor.LabelTensor`. For more details, see + :meth:`torch.Tensor.clone`. + + :return: A new :class:`~pina.label_tensor.LabelTensor` instance with the + same data and labels but allocated in a different memory location. + :rtype: LabelTensor + """ + + out = LabelTensor( + super().clone(*args, **kwargs), deepcopy(self._labels) + ) + return out + + def append(self, tensor, mode="std"): + """ + Appends a given tensor to the current tensor along the last dimension. + This method supports two types of appending operations: + + 1. **Standard append** ("std"): Concatenates the input tensor with the \ + current tensor along the last dimension. + 2. **Cross append** ("cross"): Creates a cross-product of the current \ + tensor and the input tensor. + + :param tensor: The tensor to append to the current tensor. + :type tensor: LabelTensor + :param mode: The append mode to use. Defaults to ``st``. + :type mode: str, optional + :return: A new :class:`LabelTensor` instance obtained by appending the + input tensor. + :rtype: LabelTensor + + :raises ValueError: If the mode is not "std" or "cross". + """ + + if mode == "std": + # Call cat on last dimension + new_label_tensor = LabelTensor.cat( + [self, tensor], dim=self.ndim - 1 + ) + return new_label_tensor + if mode == "cross": + # Crete tensor and call cat on last dimension + tensor1 = self + tensor2 = tensor + n1 = tensor1.shape[0] + n2 = tensor2.shape[0] + tensor1 = LabelTensor(tensor1.repeat(n2, 1), labels=tensor1.labels) + tensor2 = LabelTensor( + tensor2.repeat_interleave(n1, dim=0), labels=tensor2.labels + ) + new_label_tensor = LabelTensor.cat( + [tensor1, tensor2], dim=self.ndim - 1 + ) + return new_label_tensor + raise ValueError('mode must be either "std" or "cross"') + + @staticmethod + def vstack(tensors): + """ + Stack tensors vertically. For more details, see :meth:`torch.vstack`. + + :param list of LabelTensor label_tensors: The + :class:`~pina.label_tensor.LabelTensor` instances to stack. They + need to have equal labels. + :return: A new :class:`~pina.label_tensor.LabelTensor` instance obtained + by stacking the input tensors vertically. + :rtype: LabelTensor + """ + + return LabelTensor.cat(tensors, dim=0) + + # This method is used to update labels + def _update_single_label(self, index, dim): + """ + Update the labels of the tensor based on the index (or list of indices). + + :param index: Index of dof to retain. + :type index: int | slice | list[int] | tuple[int] | torch.Tensor + :param int dim: Dimension of the indexes in the original tensor. + :return: The updated labels for the specified dimension. + :rtype: list[int] + :raises: ValueError: If the index type is not supported. + """ + old_dof = self._labels[dim]["dof"] + # Handle slicing + if isinstance(index, slice): + new_dof = old_dof[index] + # Handle single integer index + elif isinstance(index, int): + new_dof = [old_dof[index]] + # Handle lists or tensors + elif isinstance(index, (list, torch.Tensor)): + # Handle list of bools + if isinstance(index, torch.Tensor) and index.dtype == torch.bool: + index = index.nonzero().squeeze() + new_dof = ( + [old_dof[i] for i in index] + if isinstance(old_dof, list) + else index + ) + else: + raise NotImplementedError( + f"Unsupported index type: {type(index)}. Expected slice, int, " + f"list, or torch.Tensor." + ) + return new_dof + + def __getitem__(self, index): + """ + Override the __getitem__ method to handle the labels of the + :class:`~pina.label_tensor.LabelTensor` instance. It first performs + __getitem__ operation on the :class:`torch.Tensor` part of the instance, + then updates the labels based on the index. + + :param index: The index used to access the item + :type index: int | str | tuple of int | list ot int | torch.Tensor + :return: A new :class:`~pina.label_tensor.LabelTensor` instance obtained + `__getitem__` operation on :class:`torch.Tensor` part of the + instance, with the updated labels. + :rtype: LabelTensor + + :raises KeyError: If an invalid label index is provided. + :raises IndexError: If an invalid index is accessed in the tensor. + """ + + # Handle string index + if isinstance(index, str) or ( + isinstance(index, (tuple, list)) + and all(isinstance(i, str) for i in index) + ): + return self.extract(index) + + # Retrieve selected tensor and labels + selected_tensor = super().__getitem__(index) + if not hasattr(self, "_labels"): + return selected_tensor + + original_labels = self._labels + updated_labels = copy(original_labels) + + # Ensure the index is iterable + if not isinstance(index, tuple): + index = [index] + + # Update labels based on the index + offset = 0 + removed = 0 + for dim, idx in enumerate(index): + if dim in original_labels: + if isinstance(idx, int): + # Compute the working dimension considering the removed + # dimensions due to int index on a non labled dimension + dim_ = dim - removed + selected_tensor = selected_tensor.unsqueeze(dim_) + if idx != slice(None): + # Update the labels for the selected dimension + updated_labels[offset] = { + "dof": self._update_single_label(idx, dim), + "name": original_labels[dim]["name"], + } + else: + # Adjust label keys if dimension is reduced (case of integer + # index on a non-labeled dimension) + if isinstance(idx, int): + updated_labels = { + key - 1 if key > dim else key: value + for key, value in updated_labels.items() + } + removed += 1 + continue + offset += 1 + + # Update the selected tensor's labels + selected_tensor._labels = updated_labels + return selected_tensor + + def sort_labels(self, dim=None): + """ + Sort the labels along the specified dimension and apply. It applies the + same sorting to the tensor part of the instance. + + :param int dim: The dimension along which to sort the labels. + If ``None``, the last dimension is used. + :return: A new tensor with sorted labels along the specified dimension. + :rtype: LabelTensor + """ + + def arg_sort(lst): + return sorted(range(len(lst)), key=lambda x: lst[x]) + + if dim is None: + dim = self.ndim - 1 + if self.shape[dim] == 1: + return self + labels = self.stored_labels[dim]["dof"] + sorted_index = arg_sort(labels) + # Define an indexer to sort the tensor along the specified dimension + indexer = [slice(None)] * self.ndim + # Assigned the sorted index to the specified dimension + indexer[dim] = sorted_index + return self[tuple(indexer)] + + def __deepcopy__(self, memo): + """ + Creates a deep copy of the object. For more details, see + :meth:`copy.deepcopy`. + + :param memo: LabelTensor object to be copied. + :type memo: LabelTensor + :return: A deep copy of the original LabelTensor object. + :rtype: LabelTensor + """ + + cls = self.__class__ + result = cls(deepcopy(self.tensor), deepcopy(self.stored_labels)) + return result + + def permute(self, *dims): + """ + Permutes the dimensions of the tensor and the associated labels + accordingly. For more details, see :meth:`torch.Tensor.permute`. + + :param dims: The dimensions to permute the tensor to. + :type dims: tuple[int] | list[int] + :return: A new object with permuted dimensions and reordered labels. + :rtype: LabelTensor + """ + # Call the base class permute method + tensor = super().permute(*dims) + + # Update lables + labels = self._labels + keys_list = list(*dims) + labels = {keys_list.index(k): v for k, v in labels.items()} + + # Assign labels to the new tensor + tensor._labels = labels + return tensor + + def detach(self): + """ + Detaches the tensor from the computation graph and retains the stored + labels. For more details, see :meth:`torch.Tensor.detach`. + + :return: A new tensor detached from the computation graph. + :rtype: LabelTensor + """ + + lt = super().detach() + + # Copy the labels to the new tensor only if present + if hasattr(self, "_labels"): + lt._labels = self.stored_labels + return lt + + @staticmethod + def summation(tensors): + """ + Computes the summation of a list of + :class:`~pina.label_tensor.LabelTensor` instances. + + + :param list[LabelTensor] tensors: A list of tensors to sum. All + tensors must have the same shape and labels. + :return: A new `LabelTensor` containing the element-wise sum of the + input tensors. + :rtype: LabelTensor + + :raises ValueError: If the input `tensors` list is empty. + :raises RuntimeError: If the tensors have different shapes and/or + mismatched labels. + """ + + if not tensors: + raise ValueError("The tensors list must not be empty.") + + if len(tensors) == 1: + return tensors[0] + + # Initialize result tensor and labels + data = torch.zeros_like(tensors[0].tensor).to(tensors[0].device) + last_dim_labels = [] + + # Accumulate tensors + for tensor in tensors: + data += tensor.tensor + last_dim_labels.append(tensor.labels) + + # Construct last dimension labels + last_dim_labels = ["+".join(items) for items in zip(*last_dim_labels)] + + # Update the labels for the resulting tensor + labels = {k: copy(v) for k, v in tensors[0].stored_labels.items()} + labels[tensors[0].ndim - 1] = { + "dof": last_dim_labels, + "name": tensors[0].name, + } + + return LabelTensor(data, labels) + + def reshape(self, *shape): + """ + Override the reshape method to update the labels of the tensor. + For more details, see :meth:`torch.Tensor.reshape`. + + :param tuple of int shape: The new shape of the tensor. + :return: A new :class:`~pina.label_tensor.LabelTensor` instance with the + updated shape and labels. + :rtype: LabelTensor + """ + + # As for now the reshape method is used only in the context of the + # dataset, the labels are not + tensor = super().reshape(*shape) + if not hasattr(self, "_labels") or shape != (-1, *self.shape[2:]): + return tensor + tensor.labels = self.labels + return tensor diff --git a/pina/_src/core/operator.py b/pina/_src/core/operator.py new file mode 100644 index 000000000..8ed28c3a6 --- /dev/null +++ b/pina/_src/core/operator.py @@ -0,0 +1,482 @@ +"""Module for vectorized differential operators implementation. + +Differential operators are used to define differential problems and are +implemented to run efficiently on various accelerators, including CPU, GPU, TPU, +and MPS. + +Each differential operator takes the following inputs: +- A tensor on which the operator is applied. +- A tensor with respect to which the operator is computed. +- The names of the output variables for which the operator is evaluated. +- The names of the variables with respect to which the operator is computed. + +Each differential operator has its fast version, which performs no internal +checks on input and output tensors. For these methods, the user is always +required to specify both ``components`` and ``d`` as lists of strings. +""" + +import torch +from pina._src.core.label_tensor import LabelTensor + + +def _check_values(output_, input_, components, d): + """ + Perform checks on arguments of differential operators. + + :param LabelTensor output_: The output tensor on which the operator is + computed. + :param LabelTensor input_: The input tensor with respect to which the + operator is computed. + :param components: The names of the output variables for which to compute + the operator. It must be a subset of the output labels. + If ``None``, all output variables are considered. Default is ``None``. + :type components: str | list[str] + :param d: The names of the input variables with respect to which the + operator is computed. It must be a subset of the input labels. + If ``None``, all input variables are considered. Default is ``None``. + :type d: str | list[str] + :raises TypeError: If the input tensor is not a LabelTensor. + :raises TypeError: If the output tensor is not a LabelTensor. + :raises RuntimeError: If derivative labels are missing from the ``input_``. + :raises RuntimeError: If component labels are missing from the ``output_``. + :return: The components and d lists. + :rtype: tuple[list[str], list[str]] + """ + # Check if the input is a LabelTensor + if not isinstance(input_, LabelTensor): + raise TypeError("Input must be a LabelTensor.") + + # Check if the output is a LabelTensor + if not isinstance(output_, LabelTensor): + raise TypeError("Output must be a LabelTensor.") + + # If no labels are provided, use all labels + d = d or input_.labels + components = components or output_.labels + + # Convert to list if not already + d = d if isinstance(d, list) else [d] + components = components if isinstance(components, list) else [components] + + # Check if all labels are present in the input tensor + if not all(di in input_.labels for di in d): + raise RuntimeError("Derivative labels missing from input tensor.") + + # Check if all labels are present in the output tensor + if not all(c in output_.labels for c in components): + raise RuntimeError("Component label missing from output tensor.") + + return components, d + + +def _scalar_grad(output_, input_, d): + """ + Compute the gradient of a scalar-valued ``output_``. + + :param LabelTensor output_: The output tensor on which the gradient is + computed. It must be a column tensor. + :param LabelTensor input_: The input tensor with respect to which the + gradient is computed. + :param list[str] d: The names of the input variables with respect to + which the gradient is computed. It must be a subset of the input + labels. If ``None``, all input variables are considered. + :return: The computed gradient tensor. + :rtype: LabelTensor + """ + grad_out = torch.autograd.grad( + outputs=output_, + inputs=input_, + grad_outputs=torch.ones_like(output_), + create_graph=True, + retain_graph=True, + allow_unused=True, + )[0] + + return grad_out[..., [input_.labels.index(i) for i in d]] + + +def _scalar_laplacian(output_, input_, d): + """ + Compute the laplacian of a scalar-valued ``output_``. + + :param LabelTensor output_: The output tensor on which the laplacian is + computed. It must be a column tensor. + :param LabelTensor input_: The input tensor with respect to which the + laplacian is computed. + :param list[str] d: The names of the input variables with respect to + which the laplacian is computed. It must be a subset of the input + labels. If ``None``, all input variables are considered. + :return: The computed laplacian tensor. + :rtype: LabelTensor + """ + first_grad = fast_grad( + output_=output_, input_=input_, components=output_.labels, d=d + ) + second_grad = fast_grad( + output_=first_grad, input_=input_, components=first_grad.labels, d=d + ) + labels_to_extract = [f"d{c}d{d_}" for c, d_ in zip(first_grad.labels, d)] + return torch.sum( + second_grad.extract(labels_to_extract), dim=-1, keepdim=True + ) + + +def fast_grad(output_, input_, components, d): + """ + Compute the gradient of the ``output_`` with respect to the ``input``. + + Unlike ``grad``, this function performs no internal checks on input and + output tensors. The user is required to specify both ``components`` and + ``d`` as lists of strings. It is designed to enhance computation speed. + + This operator supports both vector-valued and scalar-valued functions with + one or multiple input coordinates. + + :param LabelTensor output_: The output tensor on which the gradient is + computed. + :param LabelTensor input_: The input tensor with respect to which the + gradient is computed. + :param list[str] components: The names of the output variables for which to + compute the gradient. It must be a subset of the output labels. + :param list[str] d: The names of the input variables with respect to which + the gradient is computed. It must be a subset of the input labels. + :return: The computed gradient tensor. + :rtype: LabelTensor + """ + # Scalar gradient + if output_.shape[-1] == 1: + return LabelTensor( + _scalar_grad(output_=output_, input_=input_, d=d), + labels=[f"d{output_.labels[0]}d{i}" for i in d], + ) + + # Vector gradient + grads = torch.cat( + [ + _scalar_grad(output_=output_.extract(c), input_=input_, d=d) + for c in components + ], + dim=-1, + ) + + return LabelTensor( + grads, labels=[f"d{c}d{i}" for c in components for i in d] + ) + + +def fast_div(output_, input_, components, d): + """ + Compute the divergence of the ``output_`` with respect to ``input``. + + Unlike ``div``, this function performs no internal checks on input and + output tensors. The user is required to specify both ``components`` and + ``d`` as lists of strings. It is designed to enhance computation speed. + + This operator supports vector-valued functions with multiple input + coordinates. + + :param LabelTensor output_: The output tensor on which the divergence is + computed. + :param LabelTensor input_: The input tensor with respect to which the + divergence is computed. + :param list[str] components: The names of the output variables for which to + compute the divergence. It must be a subset of the output labels. + :param list[str] d: The names of the input variables with respect to which + the divergence is computed. It must be a subset of the input labels. + :rtype: LabelTensor + """ + grad_out = fast_grad( + output_=output_, input_=input_, components=components, d=d + ) + tensors_to_sum = [ + grad_out.extract(f"d{c}d{d_}") for c, d_ in zip(components, d) + ] + + return LabelTensor.summation(tensors_to_sum) + + +def fast_laplacian(output_, input_, components, d, method="std"): + """ + Compute the laplacian of the ``output_`` with respect to ``input``. + + Unlike ``laplacian``, this function performs no internal checks on input and + output tensors. The user is required to specify both ``components`` and + ``d`` as lists of strings. It is designed to enhance computation speed. + + This operator supports both vector-valued and scalar-valued functions with + one or multiple input coordinates. + + :param LabelTensor output_: The output tensor on which the laplacian is + computed. + :param LabelTensor input_: The input tensor with respect to which the + laplacian is computed. + :param list[str] components: The names of the output variables for which to + compute the laplacian. It must be a subset of the output labels. + :param list[str] d: The names of the input variables with respect to which + the laplacian is computed. It must be a subset of the input labels. + :param str method: The method used to compute the Laplacian. Available + methods are ``std`` and ``divgrad``. The ``std`` method computes the + trace of the Hessian matrix, while the ``divgrad`` method computes the + divergence of the gradient. Default is ``std``. + :return: The computed laplacian tensor. + :rtype: LabelTensor + :raises ValueError: If the passed method is neither ``std`` nor ``divgrad``. + """ + # Scalar laplacian + if output_.shape[-1] == 1: + return LabelTensor( + _scalar_laplacian(output_=output_, input_=input_, d=d), + labels=[f"dd{c}" for c in components], + ) + + # Initialize the result tensor and its labels + labels = [f"dd{c}" for c in components] + result = torch.empty( + input_.shape[0], len(components), device=output_.device + ) + + # Vector laplacian + if method == "std": + result = torch.cat( + [ + _scalar_laplacian( + output_=output_.extract(c), input_=input_, d=d + ) + for c in components + ], + dim=-1, + ) + + elif method == "divgrad": + grads = fast_grad( + output_=output_, input_=input_, components=components, d=d + ) + result = torch.cat( + [ + fast_div( + output_=grads, + input_=input_, + components=[f"d{c}d{i}" for i in d], + d=d, + ) + for c in components + ], + dim=-1, + ) + + else: + raise ValueError( + "Invalid method. Available methods are ``std`` and ``divgrad``." + ) + + return LabelTensor(result, labels=labels) + + +def fast_advection(output_, input_, velocity_field, components, d): + """ + Perform the advection operation on the ``output_`` with respect to the + ``input``. This operator supports vector-valued functions with multiple + input coordinates. + + Unlike ``advection``, this function performs no internal checks on input and + output tensors. The user is required to specify both ``components`` and + ``d`` as lists of strings. It is designed to enhance computation speed. + + :param LabelTensor output_: The output tensor on which the advection is + computed. It includes both the velocity and the quantity to be advected. + :param LabelTensor input_: the input tensor with respect to which advection + is computed. + :param list[str] velocity_field: The name of the output variables used as + velocity field. It must be chosen among the output labels. + :param list[str] components: The names of the output variables for which to + compute the advection. It must be a subset of the output labels. + :param list[str] d: The names of the input variables with respect to which + the advection is computed. It must be a subset of the input labels. + :return: The computed advection tensor. + :rtype: LabelTensor + """ + # Add a dimension to the velocity field for following operations + velocity = output_.extract(velocity_field).unsqueeze(-1) + + # Compute the gradient + grads = fast_grad( + output_=output_, input_=input_, components=components, d=d + ) + + # Reshape into [..., len(filter_components), len(d)] + tmp = grads.reshape(*output_.shape[:-1], len(components), len(d)) + + # Transpose to [..., len(d), len(filter_components)] + tmp = tmp.transpose(-1, -2) + + adv = (tmp * velocity).sum(dim=tmp.tensor.ndim - 2) + return LabelTensor(adv, labels=[f"adv_{c}" for c in components]) + + +def grad(output_, input_, components=None, d=None): + """ + Compute the gradient of the ``output_`` with respect to the ``input``. + + This operator supports both vector-valued and scalar-valued functions with + one or multiple input coordinates. + + :param LabelTensor output_: The output tensor on which the gradient is + computed. + :param LabelTensor input_: The input tensor with respect to which the + gradient is computed. + :param components: The names of the output variables for which to compute + the gradient. It must be a subset of the output labels. + If ``None``, all output variables are considered. Default is ``None``. + :type components: str | list[str] + :param d: The names of the input variables with respect to which the + gradient is computed. It must be a subset of the input labels. + If ``None``, all input variables are considered. Default is ``None``. + :type d: str | list[str] + :raises TypeError: If the input tensor is not a LabelTensor. + :raises TypeError: If the output tensor is not a LabelTensor. + :raises RuntimeError: If derivative labels are missing from the ``input_``. + :raises RuntimeError: If component labels are missing from the ``output_``. + :return: The computed gradient tensor. + :rtype: LabelTensor + """ + components, d = _check_values( + output_=output_, input_=input_, components=components, d=d + ) + return fast_grad(output_=output_, input_=input_, components=components, d=d) + + +def div(output_, input_, components=None, d=None): + """ + Compute the divergence of the ``output_`` with respect to ``input``. + + This operator supports vector-valued functions with multiple input + coordinates. + + :param LabelTensor output_: The output tensor on which the divergence is + computed. + :param LabelTensor input_: The input tensor with respect to which the + divergence is computed. + :param components: The names of the output variables for which to compute + the divergence. It must be a subset of the output labels. + If ``None``, all output variables are considered. Default is ``None``. + :type components: str | list[str] + :param d: The names of the input variables with respect to which the + divergence is computed. It must be a subset of the input labels. + If ``None``, all input variables are considered. Default is ``None``. + :type components: str | list[str] + :raises TypeError: If the input tensor is not a LabelTensor. + :raises TypeError: If the output tensor is not a LabelTensor. + :raises ValueError: If the length of ``components`` and ``d`` do not match. + :return: The computed divergence tensor. + :rtype: LabelTensor + """ + components, d = _check_values( + output_=output_, input_=input_, components=components, d=d + ) + + # Components and d must be of the same length + if len(components) != len(d): + raise ValueError( + "Divergence requires components and d to be of the same length." + ) + + return fast_div(output_=output_, input_=input_, components=components, d=d) + + +def laplacian(output_, input_, components=None, d=None, method="std"): + """ + Compute the laplacian of the ``output_`` with respect to ``input``. + + This operator supports both vector-valued and scalar-valued functions with + one or multiple input coordinates. + + :param LabelTensor output_: The output tensor on which the laplacian is + computed. + :param LabelTensor input_: The input tensor with respect to which the + laplacian is computed. + :param components: The names of the output variables for which to + compute the laplacian. It must be a subset of the output labels. + If ``None``, all output variables are considered. Default is ``None``. + :type components: str | list[str] + :param d: The names of the input variables with respect to which + the laplacian is computed. It must be a subset of the input labels. + If ``None``, all input variables are considered. Default is ``None``. + :type d: str | list[str] + :param str method: The method used to compute the Laplacian. Available + methods are ``std`` and ``divgrad``. The ``std`` method computes the + trace of the Hessian matrix, while the ``divgrad`` method computes the + divergence of the gradient. Default is ``std``. + :raises TypeError: If the input tensor is not a LabelTensor. + :raises TypeError: If the output tensor is not a LabelTensor. + :raises ValueError: If the passed method is neither ``std`` nor ``divgrad``. + :return: The computed laplacian tensor. + :rtype: LabelTensor + """ + components, d = _check_values( + output_=output_, input_=input_, components=components, d=d + ) + + return fast_laplacian( + output_=output_, + input_=input_, + components=components, + d=d, + method=method, + ) + + +def advection(output_, input_, velocity_field, components=None, d=None): + """ + Perform the advection operation on the ``output_`` with respect to the + ``input``. This operator supports vector-valued functions with multiple + input coordinates. + + :param LabelTensor output_: The output tensor on which the advection is + computed. It includes both the velocity and the quantity to be advected. + :param LabelTensor input_: the input tensor with respect to which advection + is computed. + :param velocity_field: The name of the output variables used as velocity + field. It must be chosen among the output labels. + :type velocity_field: str | list[str] + :param components: The names of the output variables for which to compute + the advection. It must be a subset of the output labels. + If ``None``, all output variables are considered. Default is ``None``. + :type components: str | list[str] + :param d: The names of the input variables with respect to which the + advection is computed. It must be a subset of the input labels. + If ``None``, all input variables are considered. Default is ``None``. + :type d: str | list[str] + :raises TypeError: If the input tensor is not a LabelTensor. + :raises TypeError: If the output tensor is not a LabelTensor. + :raises RuntimeError: If the velocity field is not a subset of the output + labels. + :raises RuntimeError: If the dimensionality of the velocity field does not + match that of the input tensor. + :return: The computed advection tensor. + :rtype: LabelTensor + """ + components, d = _check_values( + output_=output_, input_=input_, components=components, d=d + ) + + # Map velocity_field to a list if it is a string + if isinstance(velocity_field, str): + velocity_field = [velocity_field] + + # Check if all the velocity_field labels are present in the output labels + if not all(vi in output_.labels for vi in velocity_field): + raise RuntimeError("Velocity labels missing from output tensor.") + + # Check if the velocity has the same dimensionality as the input tensor + if len(velocity_field) != len(d): + raise RuntimeError( + "Velocity dimensionality does not match input dimensionality." + ) + + return fast_advection( + output_=output_, + input_=input_, + velocity_field=velocity_field, + components=components, + d=d, + ) diff --git a/pina/_src/core/trainer.py b/pina/_src/core/trainer.py new file mode 100644 index 000000000..7500be537 --- /dev/null +++ b/pina/_src/core/trainer.py @@ -0,0 +1,367 @@ +"""Module for the Trainer.""" + +import sys +import warnings +import torch +import lightning +from pina._src.core.utils import check_consistency, custom_warning_format +from pina._src.data.data_module import PinaDataModule +from pina._src.solver.supervised_solver.supervised_solver_interface import ( + SolverInterface, +) +from pina._src.solver.physics_informed_solver.pinn_interface import ( + PINNInterface, +) + +# set the warning for compile options +warnings.formatwarning = custom_warning_format +warnings.filterwarnings("always", category=UserWarning) + + +class Trainer(lightning.pytorch.Trainer): + """ + PINA custom Trainer class to extend the standard Lightning functionality. + + This class enables specific features or behaviors required by the PINA + framework. It modifies the standard + :class:`lightning.pytorch.Trainer ` + class to better support the training process in PINA. + """ + + def __init__( + self, + solver, + batch_size=None, + train_size=1.0, + test_size=0.0, + val_size=0.0, + compile=None, + repeat=None, + automatic_batching=None, + num_workers=None, + pin_memory=None, + shuffle=None, + **kwargs, + ): + """ + Initialization of the :class:`Trainer` class. + + :param SolverInterface solver: A + :class:`~pina.solver.solver.SolverInterface` solver used to solve a + :class:`~pina.problem.abstract_problem.AbstractProblem`. + :param int batch_size: The number of samples per batch to load. + If ``None``, all samples are loaded and data is not batched. + Default is ``None``. + :param float train_size: The percentage of elements to include in the + training dataset. Default is ``1.0``. + :param float test_size: The percentage of elements to include in the + test dataset. Default is ``0.0``. + :param float val_size: The percentage of elements to include in the + validation dataset. Default is ``0.0``. + :param bool compile: If ``True``, the model is compiled before training. + Default is ``False``. For Windows users, it is always disabled. Not + supported for python version greater or equal than 3.14. + :param bool repeat: Whether to repeat the dataset data in each + condition during training. For further details, see the + :class:`~pina.data.data_module.PinaDataModule` class. Default is + ``False``. + :param bool automatic_batching: If ``True``, automatic PyTorch batching + is performed, otherwise the items are retrieved from the dataset + all at once. For further details, see the + :class:`~pina.data.data_module.PinaDataModule` class. Default is + ``False``. + :param int num_workers: The number of worker threads for data loading. + Default is ``0`` (serial loading). + :param bool pin_memory: Whether to use pinned memory for faster data + transfer to GPU. Default is ``False``. + :param bool shuffle: Whether to shuffle the data during training. + Default is ``True``. + :param dict kwargs: Additional keyword arguments that specify the + training setup. These can be selected from the `pytorch-lightning + Trainer API + `_. + """ + # check consistency for init types + self._check_input_consistency( + solver=solver, + train_size=train_size, + test_size=test_size, + val_size=val_size, + repeat=repeat, + automatic_batching=automatic_batching, + compile=compile, + ) + pin_memory, num_workers, shuffle, batch_size = ( + self._check_consistency_and_set_defaults( + pin_memory, num_workers, shuffle, batch_size + ) + ) + + # inference mode set to false when validating/testing PINNs otherwise + # gradient is not tracked and optimization_cycle fails + if isinstance(solver, PINNInterface): + kwargs["inference_mode"] = False + + # Logging depends on the batch size, when batch_size is None then + # log_every_n_steps should be zero + if batch_size is None: + kwargs["log_every_n_steps"] = 0 + else: + kwargs.setdefault("log_every_n_steps", 50) # default for lightning + + # Setting default kwargs, overriding lightning defaults + kwargs.setdefault("enable_progress_bar", True) + + super().__init__(**kwargs) + + # checking compilation and automatic batching + # compilation disabled for Windows and for Python 3.14+ + if ( + compile is None + or sys.platform == "win32" + or sys.version_info >= (3, 14) + ): + compile = False + warnings.warn( + "Compilation is disabled for Python 3.14+ and for Windows.", + UserWarning, + ) + + repeat = repeat if repeat is not None else False + + automatic_batching = ( + automatic_batching if automatic_batching is not None else False + ) + + # set attributes + self.compile = compile + self.solver = solver + self.batch_size = batch_size + self._move_to_device() + self.data_module = None + self._create_datamodule( + train_size=train_size, + test_size=test_size, + val_size=val_size, + batch_size=batch_size, + repeat=repeat, + automatic_batching=automatic_batching, + pin_memory=pin_memory, + num_workers=num_workers, + shuffle=shuffle, + ) + + # logging + self.logging_kwargs = { + "sync_dist": bool( + len(self._accelerator_connector._parallel_devices) > 1 + ), + "on_step": bool(kwargs["log_every_n_steps"] > 0), + "prog_bar": bool(kwargs["enable_progress_bar"]), + "on_epoch": True, + } + + def _move_to_device(self): + """ + Moves the ``unknown_parameters`` of an instance of + :class:`~pina.problem.abstract_problem.AbstractProblem` to the + :class:`Trainer` device. + """ + device = self._accelerator_connector._parallel_devices[0] + # move parameters to device + pb = self.solver.problem + if hasattr(pb, "unknown_parameters"): + for key in pb.unknown_parameters: + pb.unknown_parameters[key] = torch.nn.Parameter( + pb.unknown_parameters[key].data.to(device) + ) + + def _create_datamodule( + self, + train_size, + test_size, + val_size, + batch_size, + repeat, + automatic_batching, + pin_memory, + num_workers, + shuffle, + ): + """ + This method is designed to handle the creation of a data module when + resampling is needed during training. Instead of manually defining and + modifying the trainer's dataloaders, this method is called to + automatically configure the data module. + + :param float train_size: The percentage of elements to include in the + training dataset. + :param float test_size: The percentage of elements to include in the + test dataset. + :param float val_size: The percentage of elements to include in the + validation dataset. + :param int batch_size: The number of samples per batch to load. + :param bool repeat: Whether to repeat the dataset data in each + condition during training. + :param bool automatic_batching: Whether to perform automatic batching + with PyTorch. + :param bool pin_memory: Whether to use pinned memory for faster data + transfer to GPU. + :param int num_workers: The number of worker threads for data loading. + :param bool shuffle: Whether to shuffle the data during training. + :raises RuntimeError: If not all conditions are sampled. + """ + if not self.solver.problem.are_all_domains_discretised: + error_message = "\n".join( + [ + f"""{" " * 13} ---> Domain {key} { + "sampled" if key in self.solver.problem.discretised_domains + else + "not sampled"}""" + for key in self.solver.problem.domains.keys() + ] + ) + raise RuntimeError( + "Cannot create Trainer if not all conditions " + "are sampled. The Trainer got the following:\n" + f"{error_message}" + ) + self.data_module = PinaDataModule( + self.solver.problem, + train_size=train_size, + test_size=test_size, + val_size=val_size, + batch_size=batch_size, + repeat=repeat, + automatic_batching=automatic_batching, + num_workers=num_workers, + pin_memory=pin_memory, + shuffle=shuffle, + ) + + def train(self, **kwargs): + """ + Manage the training process of the solver. + + :param dict kwargs: Additional keyword arguments. See `pytorch-lightning + Trainer API `_ + for details. + """ + return super().fit(self.solver, datamodule=self.data_module, **kwargs) + + def test(self, **kwargs): + """ + Manage the test process of the solver. + + :param dict kwargs: Additional keyword arguments. See `pytorch-lightning + Trainer API `_ + for details. + """ + return super().test(self.solver, datamodule=self.data_module, **kwargs) + + @property + def solver(self): + """ + Get the solver. + + :return: The solver. + :rtype: SolverInterface + """ + return self._solver + + @solver.setter + def solver(self, solver): + """ + Set the solver. + + :param SolverInterface solver: The solver to set. + """ + self._solver = solver + + @staticmethod + def _check_input_consistency( + solver, + train_size, + test_size, + val_size, + repeat, + automatic_batching, + compile, + ): + """ + Verifies the consistency of the parameters for the solver configuration. + + :param SolverInterface solver: The solver. + :param float train_size: The percentage of elements to include in the + training dataset. + :param float test_size: The percentage of elements to include in the + test dataset. + :param float val_size: The percentage of elements to include in the + validation dataset. + :param bool repeat: Whether to repeat the dataset data in each + condition during training. + :param bool automatic_batching: Whether to perform automatic batching + with PyTorch. + :param bool compile: If ``True``, the model is compiled before training. + """ + + check_consistency(solver, SolverInterface) + check_consistency(train_size, float) + check_consistency(test_size, float) + check_consistency(val_size, float) + if repeat is not None: + check_consistency(repeat, bool) + if automatic_batching is not None: + check_consistency(automatic_batching, bool) + if compile is not None: + check_consistency(compile, bool) + + @staticmethod + def _check_consistency_and_set_defaults( + pin_memory, num_workers, shuffle, batch_size + ): + """ + Checks the consistency of input parameters and sets default values + for missing or invalid parameters. + + :param bool pin_memory: Whether to use pinned memory for faster data + transfer to GPU. + :param int num_workers: The number of worker threads for data loading. + :param bool shuffle: Whether to shuffle the data during training. + :param int batch_size: The number of samples per batch to load. + """ + if pin_memory is not None: + check_consistency(pin_memory, bool) + else: + pin_memory = False + if num_workers is not None: + check_consistency(num_workers, int) + else: + num_workers = 0 + if shuffle is not None: + check_consistency(shuffle, bool) + else: + shuffle = True + if batch_size is not None: + check_consistency(batch_size, int) + return pin_memory, num_workers, shuffle, batch_size + + @property + def compile(self): + """ + Whether compilation is required or not. + + :return: ``True`` if compilation is required, ``False`` otherwise. + :rtype: bool + """ + return self._compile + + @compile.setter + def compile(self, value): + """ + Setting the value of compile. + + :param bool value: Whether compilation is required or not. + """ + check_consistency(value, bool) + self._compile = value diff --git a/pina/_src/core/type_checker.py b/pina/_src/core/type_checker.py new file mode 100644 index 000000000..e8c908ac9 --- /dev/null +++ b/pina/_src/core/type_checker.py @@ -0,0 +1,93 @@ +"""Module for enforcing type hints in Python functions.""" + +import inspect +import typing +import logging + + +def enforce_types(func): + """ + Function decorator to enforce type hints at runtime. + + This decorator checks the types of the arguments and of the return value of + the decorated function against the type hints specified in the function + signature. If the types do not match, a TypeError is raised. + Type checking is only performed when the logging level is set to `DEBUG`. + + :param Callable func: The function to be decorated. + :return: The decorated function with enforced type hints. + :rtype: Callable + + :Example: + + >>> @enforce_types + def dummy_function(a: int, b: float) -> float: + ... return a+b + + # This always works. + dummy_function(1, 2.0) + + # This raises a TypeError for the second argument, if logging is set to + # `DEBUG`. + dummy_function(1, "Hello, world!") + + + >>> @enforce_types + def dummy_function2(a: int, right: bool) -> float: + ... if right: + ... return float(a) + ... else: + ... return "Hello, world!" + + # This always works. + dummy_function2(1, right=True) + + # This raises a TypeError for the return value if logging is set to + # `DEBUG`. + dummy_function2(1, right=False) + """ + + def wrapper(*args, **kwargs): + """ + Wrapper function to enforce type hints. + + :param tuple args: Positional arguments passed to the function. + :param dict kwargs: Keyword arguments passed to the function. + :raises TypeError: If the argument or return type does not match the + specified type hints. + :return: The result of the decorated function. + :rtype: Any + """ + level = logging.getLevelName(logging.getLogger().getEffectiveLevel()) + + # Enforce type hints only in debug mode + if level != "DEBUG": + return func(*args, **kwargs) + + # Get the type hints for the function arguments + hints = typing.get_type_hints(func) + sig = inspect.signature(func) + bound = sig.bind(*args, **kwargs) + bound.apply_defaults() + + for arg_name, arg_value in bound.arguments.items(): + expected_type = hints.get(arg_name) + if expected_type and not isinstance(arg_value, expected_type): + raise TypeError( + f"Argument '{arg_name}' must be {expected_type.__name__}, " + f"but got {type(arg_value).__name__}!" + ) + + # Get the type hints for the return values + return_type = hints.get("return") + result = func(*args, **kwargs) + + if return_type and not isinstance(result, return_type): + raise TypeError( + f"Return value must be {return_type.__name__}, " + f"but got {type(result).__name__}!" + ) + + return result + + return wrapper diff --git a/pina/_src/core/utils.py b/pina/_src/core/utils.py new file mode 100644 index 000000000..ea70ed944 --- /dev/null +++ b/pina/_src/core/utils.py @@ -0,0 +1,270 @@ +"""Module for utility functions.""" + +import types +from functools import reduce +import torch + +from pina._src.core.label_tensor import LabelTensor + + +# Codacy error unused parameters +def custom_warning_format( + message, category, filename, lineno, file=None, line=None +): + """ + Custom warning formatting function. + + :param str message: The warning message. + :param Warning category: The warning category. + :param str filename: The filename where the warning is raised. + :param int lineno: The line number where the warning is raised. + :param str file: The file object where the warning is raised. + Default is None. + :param int line: The line where the warning is raised. + :return: The formatted warning message. + :rtype: str + """ + return f"{filename}: {category.__name__}: {message}\n" + + +def check_consistency(object_, object_instance, subclass=False): + """ + Check if an object maintains inheritance consistency. + + This function checks whether a given object is an instance of a specified + class or, if ``subclass=True``, whether it is a subclass of the specified + class. + + :param object: The object to check. + :type object: Iterable | Object + :param Object object_instance: The expected parent class. + :param bool subclass: If True, checks whether ``object_`` is a subclass + of ``object_instance`` instead of an instance. Default is ``False``. + :raises ValueError: If ``object_`` does not inherit from ``object_instance`` + as expected. + """ + if not isinstance(object_, (list, set, tuple)): + object_ = [object_] + + for obj in object_: + is_class = isinstance(obj, type) + expected_type_name = ( + object_instance.__name__ + if isinstance(object_instance, type) + else str(object_instance) + ) + + if subclass: + if not is_class: + raise ValueError( + f"You passed {repr(obj)} " + f"(an instance of {type(obj).__name__}), " + f"but a {expected_type_name} class was expected. " + f"Please pass a {expected_type_name} class or a " + "derived one." + ) + if not issubclass(obj, object_instance): + raise ValueError( + f"You passed {obj.__name__} class, but a " + f"{expected_type_name} class was expected. " + f"Please pass a {expected_type_name} class or a " + "derived one." + ) + else: + if is_class: + raise ValueError( + f"You passed {obj.__name__} class, but a " + f"{expected_type_name} instance was expected. " + f"Please pass a {expected_type_name} instance." + ) + if not isinstance(obj, object_instance): + raise ValueError( + f"You passed {repr(obj)} " + f"(an instance of {type(obj).__name__}), " + f"but a {expected_type_name} instance was expected. " + f"Please pass a {expected_type_name} instance." + ) + + +def labelize_forward(forward, input_variables, output_variables): + """ + Decorator to enable or disable the use of + :class:`~pina.label_tensor.LabelTensor` during the forward pass. + + :param Callable forward: The forward function of a :class:`torch.nn.Module`. + :param list[str] input_variables: The names of the input variables of a + :class:`~pina.problem.abstract_problem.AbstractProblem`. + :param list[str] output_variables: The names of the output variables of a + :class:`~pina.problem.abstract_problem.AbstractProblem`. + :return: The decorated forward function. + :rtype: Callable + """ + + def wrapper(x, *args, **kwargs): + """ + Decorated forward function. + + :param LabelTensor x: The labelized input of the forward pass of an + instance of :class:`torch.nn.Module`. + :param Iterable args: Additional positional arguments passed to + ``forward`` method. + :param dict kwargs: Additional keyword arguments passed to + ``forward`` method. + :return: The labelized output of the forward pass of an instance of + :class:`torch.nn.Module`. + :rtype: LabelTensor + """ + x = x.extract(input_variables) + output = forward(x, *args, **kwargs) + # keep it like this, directly using LabelTensor(...) raises errors + # when compiling the code + output = output.as_subclass(LabelTensor) + output.labels = output_variables + return output + + return wrapper + + +def merge_tensors(tensors): + """ + Merge a list of :class:`~pina.label_tensor.LabelTensor` instances into a + single :class:`~pina.label_tensor.LabelTensor` tensor, by applying + iteratively the cartesian product. + + :param list[LabelTensor] tensors: The list of tensors to merge. + :raises ValueError: If the list of tensors is empty. + :return: The merged tensor. + :rtype: LabelTensor + """ + if tensors: + return reduce(merge_two_tensors, tensors[1:], tensors[0]) + raise ValueError("Expected at least one tensor") + + +def merge_two_tensors(tensor1, tensor2): + """ + Merge two :class:`~pina.label_tensor.LabelTensor` instances into a single + :class:`~pina.label_tensor.LabelTensor` tensor, by applying the cartesian + product. + + :param LabelTensor tensor1: The first tensor to merge. + :param LabelTensor tensor2: The second tensor to merge. + :return: The merged tensor. + :rtype: LabelTensor + """ + n1 = tensor1.shape[0] + n2 = tensor2.shape[0] + + tensor1 = LabelTensor(tensor1.repeat(n2, 1), labels=tensor1.labels) + tensor2 = LabelTensor( + tensor2.repeat_interleave(n1, dim=0), labels=tensor2.labels + ) + return tensor1.append(tensor2) + + +def torch_lhs(n, dim): + """ + The Latin Hypercube Sampling torch routine, sampling in :math:`[0, 1)`$. + + :param int n: The number of points to sample. + :param int dim: The number of dimensions of the sampling space. + :raises TypeError: If `n` or `dim` are not integers. + :raises ValueError: If `dim` is less than 1. + :return: The sampled points. + :rtype: torch.tensor + """ + + if not isinstance(n, int): + raise TypeError("number of point n must be int") + + if not isinstance(dim, int): + raise TypeError("dim must be int") + + if dim < 1: + raise ValueError("dim must be greater than one") + + samples = torch.rand(size=(n, dim)) + + perms = torch.tile(torch.arange(1, n + 1), (dim, 1)) + + for row in range(dim): + idx_perm = torch.randperm(perms.shape[-1]) + perms[row, :] = perms[row, idx_perm] + + perms = perms.T + + samples = (perms - samples) / n + + return samples + + +def is_function(f): + """ + Check if the given object is a function or a lambda. + + :param Object f: The object to be checked. + :return: ``True`` if ``f`` is a function, ``False`` otherwise. + :rtype: bool + """ + return callable(f) + + +def chebyshev_roots(n): + """ + Compute the roots of the Chebyshev polynomial of degree ``n``. + + :param int n: The number of roots to return. + :return: The roots of the Chebyshev polynomials. + :rtype: torch.Tensor + """ + pi = torch.acos(torch.zeros(1)).item() * 2 + k = torch.arange(n) + nodes = torch.sort(torch.cos(pi * (k + 0.5) / n))[0] + return nodes + + +def check_positive_integer(value, strict=True): + """ + Check if the value is a positive integer. + + :param int value: The value to check. + :param bool strict: If True, the value must be strictly positive. + Default is True. + :raises AssertionError: If the value is not a positive integer. + """ + if strict: + assert ( + isinstance(value, int) and value > 0 + ), f"Expected a strictly positive integer, got {value}." + else: + assert ( + isinstance(value, int) and value >= 0 + ), f"Expected a non-negative integer, got {value}." + + +def in_range(value, range_vals, strict=True): + """ + Check if a value is within a specified range. + + :param int value: The integer value to check. + :param list[int] range_vals: A list of two integers representing the range + limits. The first element specifies the lower bound, and the second + specifies the upper bound. + :param bool strict: If True, the value must be strictly positive. + Default is True. + :return: True if the value satisfies the range condition, False otherwise. + :rtype: bool + """ + # Validate inputs + check_consistency(value, (float, int)) + check_consistency(range_vals, (float, int)) + assert ( + isinstance(range_vals, list) and len(range_vals) == 2 + ), "range_vals must be a list of two integers [lower, upper]" + lower, upper = range_vals + + # Check the range + if strict: + return lower < value < upper + + return lower <= value <= upper diff --git a/pina/_src/data/__init__.py b/pina/_src/data/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/data/data_module.py b/pina/_src/data/data_module.py similarity index 99% rename from pina/data/data_module.py rename to pina/_src/data/data_module.py index 52b52a3fa..f45236f0f 100644 --- a/pina/data/data_module.py +++ b/pina/_src/data/data_module.py @@ -8,10 +8,10 @@ from lightning.pytorch import LightningDataModule import torch from torch_geometric.data import Data -from torch.utils.data import DataLoader, SequentialSampler, RandomSampler +from torch.utils.data import DataLoader, SequentialSampler from torch.utils.data.distributed import DistributedSampler -from ..label_tensor import LabelTensor -from .dataset import PinaDatasetFactory, PinaTensorDataset +from pina._src.core.label_tensor import LabelTensor +from pina._src.data.dataset import PinaDatasetFactory, PinaTensorDataset class DummyDataloader: diff --git a/pina/data/dataset.py b/pina/_src/data/dataset.py similarity index 99% rename from pina/data/dataset.py rename to pina/_src/data/dataset.py index 62e3913d8..bf2f168e4 100644 --- a/pina/data/dataset.py +++ b/pina/_src/data/dataset.py @@ -3,7 +3,7 @@ from abc import abstractmethod, ABC from torch.utils.data import Dataset from torch_geometric.data import Data -from ..graph import Graph, LabelBatch +from pina._src.core.graph import Graph, LabelBatch class PinaDatasetFactory: diff --git a/pina/_src/domain/__init__.py b/pina/_src/domain/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/domain/base_domain.py b/pina/_src/domain/base_domain.py similarity index 97% rename from pina/domain/base_domain.py rename to pina/_src/domain/base_domain.py index c7bef9700..3316fabfd 100644 --- a/pina/domain/base_domain.py +++ b/pina/_src/domain/base_domain.py @@ -2,8 +2,8 @@ from copy import deepcopy from abc import ABCMeta -from .domain_interface import DomainInterface -from ..utils import check_consistency, check_positive_integer +from pina._src.domain.domain_interface import DomainInterface +from pina._src.core.utils import check_consistency, check_positive_integer class BaseDomain(DomainInterface, metaclass=ABCMeta): diff --git a/pina/domain/base_operation.py b/pina/_src/domain/base_operation.py similarity index 97% rename from pina/domain/base_operation.py rename to pina/_src/domain/base_operation.py index 8261ae431..ff83e1551 100644 --- a/pina/domain/base_operation.py +++ b/pina/_src/domain/base_operation.py @@ -2,9 +2,9 @@ from copy import deepcopy from abc import ABCMeta -from .operation_interface import OperationInterface -from .base_domain import BaseDomain -from ..utils import check_consistency +from pina._src.domain.operation_interface import OperationInterface +from pina._src.domain.base_domain import BaseDomain +from pina._src.core.utils import check_consistency class BaseOperation(OperationInterface, BaseDomain, metaclass=ABCMeta): diff --git a/pina/domain/cartesian_domain.py b/pina/_src/domain/cartesian_domain.py similarity index 97% rename from pina/domain/cartesian_domain.py rename to pina/_src/domain/cartesian_domain.py index 3333a8fc3..089e3377c 100644 --- a/pina/domain/cartesian_domain.py +++ b/pina/_src/domain/cartesian_domain.py @@ -1,10 +1,10 @@ """Module for the Cartesian Domain.""" import torch -from .base_domain import BaseDomain -from .union import Union -from ..utils import torch_lhs, chebyshev_roots, check_consistency -from ..label_tensor import LabelTensor +from pina._src.domain.base_domain import BaseDomain +from pina._src.domain.union import Union +from pina._src.core.utils import torch_lhs, chebyshev_roots, check_consistency +from pina._src.core.label_tensor import LabelTensor class CartesianDomain(BaseDomain): diff --git a/pina/domain/difference.py b/pina/_src/domain/difference.py similarity index 96% rename from pina/domain/difference.py rename to pina/_src/domain/difference.py index 76807b035..ce87920e5 100644 --- a/pina/domain/difference.py +++ b/pina/_src/domain/difference.py @@ -1,8 +1,8 @@ """Module for the Difference operation.""" -from .base_operation import BaseOperation -from ..label_tensor import LabelTensor -from ..utils import check_consistency +from pina._src.domain.base_operation import BaseOperation +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency class Difference(BaseOperation): diff --git a/pina/domain/domain_interface.py b/pina/_src/domain/domain_interface.py similarity index 100% rename from pina/domain/domain_interface.py rename to pina/_src/domain/domain_interface.py diff --git a/pina/domain/ellipsoid_domain.py b/pina/_src/domain/ellipsoid_domain.py similarity index 98% rename from pina/domain/ellipsoid_domain.py rename to pina/_src/domain/ellipsoid_domain.py index ecb08e37c..402ec29a8 100644 --- a/pina/domain/ellipsoid_domain.py +++ b/pina/_src/domain/ellipsoid_domain.py @@ -2,9 +2,9 @@ from copy import deepcopy import torch -from .base_domain import BaseDomain -from ..label_tensor import LabelTensor -from ..utils import check_consistency +from pina._src.domain.base_domain import BaseDomain +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency class EllipsoidDomain(BaseDomain): diff --git a/pina/domain/exclusion.py b/pina/_src/domain/exclusion.py similarity index 97% rename from pina/domain/exclusion.py rename to pina/_src/domain/exclusion.py index 59205f3a8..914e17086 100644 --- a/pina/domain/exclusion.py +++ b/pina/_src/domain/exclusion.py @@ -1,9 +1,9 @@ """Module for the Exclusion set-operation.""" import random -from .base_operation import BaseOperation -from ..label_tensor import LabelTensor -from ..utils import check_consistency +from pina._src.domain.base_operation import BaseOperation +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency class Exclusion(BaseOperation): diff --git a/pina/domain/intersection.py b/pina/_src/domain/intersection.py similarity index 96% rename from pina/domain/intersection.py rename to pina/_src/domain/intersection.py index 105575df1..1b004556e 100644 --- a/pina/domain/intersection.py +++ b/pina/_src/domain/intersection.py @@ -1,9 +1,9 @@ """Module for the Intersection operation.""" import random -from .base_operation import BaseOperation -from ..label_tensor import LabelTensor -from ..utils import check_consistency +from pina._src.domain.base_operation import BaseOperation +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency class Intersection(BaseOperation): diff --git a/pina/domain/operation_interface.py b/pina/_src/domain/operation_interface.py similarity index 92% rename from pina/domain/operation_interface.py rename to pina/_src/domain/operation_interface.py index 9be458972..357556105 100644 --- a/pina/domain/operation_interface.py +++ b/pina/_src/domain/operation_interface.py @@ -1,7 +1,7 @@ """Module for the Operation Interface.""" from abc import ABCMeta, abstractmethod -from .domain_interface import DomainInterface +from pina._src.domain.domain_interface import DomainInterface class OperationInterface(DomainInterface, metaclass=ABCMeta): diff --git a/pina/domain/simplex_domain.py b/pina/_src/domain/simplex_domain.py similarity index 98% rename from pina/domain/simplex_domain.py rename to pina/_src/domain/simplex_domain.py index 9e3a3e58f..5dff002ce 100644 --- a/pina/domain/simplex_domain.py +++ b/pina/_src/domain/simplex_domain.py @@ -2,9 +2,9 @@ from copy import deepcopy import torch -from .base_domain import BaseDomain -from ..label_tensor import LabelTensor -from ..utils import check_consistency +from pina._src.domain.base_domain import BaseDomain +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency class SimplexDomain(BaseDomain): diff --git a/pina/domain/union.py b/pina/_src/domain/union.py similarity index 95% rename from pina/domain/union.py rename to pina/_src/domain/union.py index df094bb82..eff137df3 100644 --- a/pina/domain/union.py +++ b/pina/_src/domain/union.py @@ -1,9 +1,9 @@ """Module for the Union operation.""" import random -from .base_operation import BaseOperation -from ..label_tensor import LabelTensor -from ..utils import check_consistency +from pina._src.domain.base_operation import BaseOperation +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency class Union(BaseOperation): diff --git a/pina/_src/equation/__init__.py b/pina/_src/equation/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/equation/equation.py b/pina/_src/equation/equation.py similarity index 97% rename from pina/equation/equation.py rename to pina/_src/equation/equation.py index 057c6bcf5..a1d67628c 100644 --- a/pina/equation/equation.py +++ b/pina/_src/equation/equation.py @@ -1,7 +1,7 @@ """Module for the Equation.""" import inspect -from .equation_interface import EquationInterface +from pina._src.equation.equation_interface import EquationInterface class Equation(EquationInterface): diff --git a/pina/equation/equation_factory.py b/pina/_src/equation/equation_factory.py similarity index 99% rename from pina/equation/equation_factory.py rename to pina/_src/equation/equation_factory.py index 01560d6c1..c001d1461 100644 --- a/pina/equation/equation_factory.py +++ b/pina/_src/equation/equation_factory.py @@ -2,9 +2,9 @@ from typing import Callable import torch -from .equation import Equation -from ..operator import grad, div, laplacian -from ..utils import check_consistency +from pina._src.equation.equation import Equation +from pina._src.core.operator import grad, div, laplacian +from pina._src.core.utils import check_consistency class FixedValue(Equation): # pylint: disable=R0903 diff --git a/pina/equation/equation_interface.py b/pina/_src/equation/equation_interface.py similarity index 100% rename from pina/equation/equation_interface.py rename to pina/_src/equation/equation_interface.py diff --git a/pina/equation/system_equation.py b/pina/_src/equation/system_equation.py similarity index 96% rename from pina/equation/system_equation.py rename to pina/_src/equation/system_equation.py index 3e8550d9b..a9920a955 100644 --- a/pina/equation/system_equation.py +++ b/pina/_src/equation/system_equation.py @@ -1,9 +1,9 @@ """Module for the System of Equation.""" import torch -from .equation_interface import EquationInterface -from .equation import Equation -from ..utils import check_consistency +from pina._src.equation.equation_interface import EquationInterface +from pina._src.equation.equation import Equation +from pina._src.core.utils import check_consistency class SystemEquation(EquationInterface): diff --git a/pina/_src/loss/__init__.py b/pina/_src/loss/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/loss/linear_weighting.py b/pina/_src/loss/linear_weighting.py similarity index 94% rename from pina/loss/linear_weighting.py rename to pina/_src/loss/linear_weighting.py index 9049b52fa..e50d5151c 100644 --- a/pina/loss/linear_weighting.py +++ b/pina/_src/loss/linear_weighting.py @@ -1,7 +1,7 @@ """Module for the LinearWeighting class.""" -from ..loss import WeightingInterface -from ..utils import check_consistency, check_positive_integer +from pina._src.loss.weighting_interface import WeightingInterface +from pina._src.core.utils import check_consistency, check_positive_integer class LinearWeighting(WeightingInterface): diff --git a/pina/loss/loss_interface.py b/pina/_src/loss/loss_interface.py similarity index 100% rename from pina/loss/loss_interface.py rename to pina/_src/loss/loss_interface.py diff --git a/pina/loss/lp_loss.py b/pina/_src/loss/lp_loss.py similarity index 95% rename from pina/loss/lp_loss.py rename to pina/_src/loss/lp_loss.py index f535a5b6f..b2047d945 100644 --- a/pina/loss/lp_loss.py +++ b/pina/_src/loss/lp_loss.py @@ -1,9 +1,8 @@ """Module for the LpLoss class.""" import torch - -from ..utils import check_consistency -from .loss_interface import LossInterface +from pina._src.loss.loss_interface import LossInterface +from pina._src.core.utils import check_consistency class LpLoss(LossInterface): diff --git a/pina/loss/ntk_weighting.py b/pina/_src/loss/ntk_weighting.py similarity index 95% rename from pina/loss/ntk_weighting.py rename to pina/_src/loss/ntk_weighting.py index fe1c4fc6a..96c89fc3a 100644 --- a/pina/loss/ntk_weighting.py +++ b/pina/_src/loss/ntk_weighting.py @@ -1,8 +1,8 @@ """Module for Neural Tangent Kernel Class""" import torch -from .weighting_interface import WeightingInterface -from ..utils import check_consistency, in_range +from pina._src.loss.weighting_interface import WeightingInterface +from pina._src.core.utils import check_consistency, in_range class NeuralTangentKernelWeighting(WeightingInterface): diff --git a/pina/loss/power_loss.py b/pina/_src/loss/power_loss.py similarity index 95% rename from pina/loss/power_loss.py rename to pina/_src/loss/power_loss.py index 1edbf4f86..67986a988 100644 --- a/pina/loss/power_loss.py +++ b/pina/_src/loss/power_loss.py @@ -2,8 +2,8 @@ import torch -from ..utils import check_consistency -from .loss_interface import LossInterface +from pina._src.loss.loss_interface import LossInterface +from pina._src.core.utils import check_consistency class PowerLoss(LossInterface): diff --git a/pina/loss/scalar_weighting.py b/pina/_src/loss/scalar_weighting.py similarity index 93% rename from pina/loss/scalar_weighting.py rename to pina/_src/loss/scalar_weighting.py index 692c4937b..c97b037f9 100644 --- a/pina/loss/scalar_weighting.py +++ b/pina/_src/loss/scalar_weighting.py @@ -1,7 +1,7 @@ """Module for the Scalar Weighting.""" -from .weighting_interface import WeightingInterface -from ..utils import check_consistency +from pina._src.loss.weighting_interface import WeightingInterface +from pina._src.core.utils import check_consistency class ScalarWeighting(WeightingInterface): diff --git a/pina/loss/self_adaptive_weighting.py b/pina/_src/loss/self_adaptive_weighting.py similarity index 96% rename from pina/loss/self_adaptive_weighting.py rename to pina/_src/loss/self_adaptive_weighting.py index c796d359f..8a91f98f5 100644 --- a/pina/loss/self_adaptive_weighting.py +++ b/pina/_src/loss/self_adaptive_weighting.py @@ -1,7 +1,7 @@ """Module for Self-Adaptive Weighting class.""" import torch -from .weighting_interface import WeightingInterface +from pina._src.loss.weighting_interface import WeightingInterface class SelfAdaptiveWeighting(WeightingInterface): diff --git a/pina/loss/weighting_interface.py b/pina/_src/loss/weighting_interface.py similarity index 98% rename from pina/loss/weighting_interface.py rename to pina/_src/loss/weighting_interface.py index bc34c3181..5e75e0aaa 100644 --- a/pina/loss/weighting_interface.py +++ b/pina/_src/loss/weighting_interface.py @@ -2,7 +2,7 @@ from abc import ABCMeta, abstractmethod from typing import final -from ..utils import check_positive_integer, is_function +from pina._src.core.utils import check_positive_integer, is_function _AGGREGATE_METHODS = {"sum": sum, "mean": lambda x: sum(x) / len(x)} diff --git a/pina/_src/model/__init__.py b/pina/_src/model/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/model/average_neural_operator.py b/pina/_src/model/average_neural_operator.py similarity index 96% rename from pina/model/average_neural_operator.py rename to pina/_src/model/average_neural_operator.py index 6019b96c6..e16e3430f 100644 --- a/pina/model/average_neural_operator.py +++ b/pina/_src/model/average_neural_operator.py @@ -2,9 +2,9 @@ import torch from torch import nn -from .block.average_neural_operator_block import AVNOBlock -from .kernel_neural_operator import KernelNeuralOperator -from ..utils import check_consistency +from pina._src.model.block.average_neural_operator_block import AVNOBlock +from pina._src.model.kernel_neural_operator import KernelNeuralOperator +from pina._src.core.utils import check_consistency class AveragingNeuralOperator(KernelNeuralOperator): diff --git a/pina/_src/model/block/__init__.py b/pina/_src/model/block/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/model/block/average_neural_operator_block.py b/pina/_src/model/block/average_neural_operator_block.py similarity index 97% rename from pina/model/block/average_neural_operator_block.py rename to pina/_src/model/block/average_neural_operator_block.py index 91379abeb..4b5af8081 100644 --- a/pina/model/block/average_neural_operator_block.py +++ b/pina/_src/model/block/average_neural_operator_block.py @@ -2,7 +2,7 @@ import torch from torch import nn -from ...utils import check_consistency +from pina._src.core.utils import check_consistency class AVNOBlock(nn.Module): diff --git a/pina/model/block/convolution.py b/pina/_src/model/block/convolution.py similarity index 98% rename from pina/model/block/convolution.py rename to pina/_src/model/block/convolution.py index 666f66a66..bfe7054af 100644 --- a/pina/model/block/convolution.py +++ b/pina/_src/model/block/convolution.py @@ -2,8 +2,8 @@ from abc import ABCMeta, abstractmethod import torch -from .stride import Stride -from .utils_convolution import optimizing +from pina._src.model.block.stride import Stride +from pina._src.model.block.utils_convolution import optimizing class BaseContinuousConv(torch.nn.Module, metaclass=ABCMeta): diff --git a/pina/model/block/convolution_2d.py b/pina/_src/model/block/convolution_2d.py similarity index 98% rename from pina/model/block/convolution_2d.py rename to pina/_src/model/block/convolution_2d.py index 825ae613b..935bb0afa 100644 --- a/pina/model/block/convolution_2d.py +++ b/pina/_src/model/block/convolution_2d.py @@ -1,9 +1,9 @@ -"""Module for the Continuous Convolution class.""" +"""Module for the Continuous 2D Convolution class.""" import torch -from .convolution import BaseContinuousConv -from .utils_convolution import check_point, map_points_ -from .integral import Integral +from pina._src.model.block.convolution import BaseContinuousConv +from pina._src.model.block.utils_convolution import check_point, map_points_ +from pina._src.model.block.integral import Integral class ContinuousConvBlock(BaseContinuousConv): diff --git a/pina/model/block/embedding.py b/pina/_src/model/block/embedding.py similarity index 99% rename from pina/model/block/embedding.py rename to pina/_src/model/block/embedding.py index 1e44ec143..f9f05c119 100644 --- a/pina/model/block/embedding.py +++ b/pina/_src/model/block/embedding.py @@ -1,7 +1,7 @@ """Modules for the the Embedding blocks.""" import torch -from pina.utils import check_consistency +from pina._src.core.utils import check_consistency class PeriodicBoundaryEmbedding(torch.nn.Module): diff --git a/pina/model/block/fourier_block.py b/pina/_src/model/block/fourier_block.py similarity index 98% rename from pina/model/block/fourier_block.py rename to pina/_src/model/block/fourier_block.py index 2983c840a..2510320ec 100644 --- a/pina/model/block/fourier_block.py +++ b/pina/_src/model/block/fourier_block.py @@ -2,9 +2,9 @@ import torch from torch import nn -from ...utils import check_consistency +from pina._src.core.utils import check_consistency -from .spectral import ( +from pina._src.model.block.spectral import ( SpectralConvBlock1D, SpectralConvBlock2D, SpectralConvBlock3D, diff --git a/pina/model/block/gno_block.py b/pina/_src/model/block/gno_block.py similarity index 100% rename from pina/model/block/gno_block.py rename to pina/_src/model/block/gno_block.py diff --git a/pina/model/block/integral.py b/pina/_src/model/block/integral.py similarity index 100% rename from pina/model/block/integral.py rename to pina/_src/model/block/integral.py diff --git a/pina/model/block/low_rank_block.py b/pina/_src/model/block/low_rank_block.py similarity index 98% rename from pina/model/block/low_rank_block.py rename to pina/_src/model/block/low_rank_block.py index 1e8925d95..ad67b4dca 100644 --- a/pina/model/block/low_rank_block.py +++ b/pina/_src/model/block/low_rank_block.py @@ -2,7 +2,7 @@ import torch -from ...utils import check_consistency +from pina._src.core.utils import check_consistency class LowRankBlock(torch.nn.Module): diff --git a/pina/_src/model/block/message_passing/__init__.py b/pina/_src/model/block/message_passing/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/model/block/message_passing/deep_tensor_network_block.py b/pina/_src/model/block/message_passing/deep_tensor_network_block.py similarity index 98% rename from pina/model/block/message_passing/deep_tensor_network_block.py rename to pina/_src/model/block/message_passing/deep_tensor_network_block.py index a2de3097a..ed19578b7 100644 --- a/pina/model/block/message_passing/deep_tensor_network_block.py +++ b/pina/_src/model/block/message_passing/deep_tensor_network_block.py @@ -2,7 +2,7 @@ import torch from torch_geometric.nn import MessagePassing -from ....utils import check_positive_integer +from pina._src.core.utils import check_positive_integer class DeepTensorNetworkBlock(MessagePassing): diff --git a/pina/model/block/message_passing/en_equivariant_network_block.py b/pina/_src/model/block/message_passing/en_equivariant_network_block.py similarity index 98% rename from pina/model/block/message_passing/en_equivariant_network_block.py rename to pina/_src/model/block/message_passing/en_equivariant_network_block.py index b8057b0f1..28a197230 100644 --- a/pina/model/block/message_passing/en_equivariant_network_block.py +++ b/pina/_src/model/block/message_passing/en_equivariant_network_block.py @@ -3,8 +3,8 @@ import torch from torch_geometric.nn import MessagePassing from torch_geometric.utils import degree -from ....utils import check_positive_integer, check_consistency -from ....model import FeedForward +from pina._src.core.utils import check_positive_integer, check_consistency +from pina._src.model.feed_forward import FeedForward class EnEquivariantNetworkBlock(MessagePassing): diff --git a/pina/model/block/message_passing/equivariant_graph_neural_operator_block.py b/pina/_src/model/block/message_passing/equivariant_graph_neural_operator_block.py similarity index 97% rename from pina/model/block/message_passing/equivariant_graph_neural_operator_block.py rename to pina/_src/model/block/message_passing/equivariant_graph_neural_operator_block.py index f6c739203..8a0f30aed 100644 --- a/pina/model/block/message_passing/equivariant_graph_neural_operator_block.py +++ b/pina/_src/model/block/message_passing/equivariant_graph_neural_operator_block.py @@ -1,8 +1,10 @@ """Module for the Equivariant Graph Neural Operator block.""" import torch -from ....utils import check_positive_integer -from .en_equivariant_network_block import EnEquivariantNetworkBlock +from pina._src.core.utils import check_positive_integer +from pina._src.model.block.message_passing.en_equivariant_network_block import ( + EnEquivariantNetworkBlock, +) class EquivariantGraphNeuralOperatorBlock(torch.nn.Module): diff --git a/pina/model/block/message_passing/interaction_network_block.py b/pina/_src/model/block/message_passing/interaction_network_block.py similarity index 98% rename from pina/model/block/message_passing/interaction_network_block.py rename to pina/_src/model/block/message_passing/interaction_network_block.py index 7c6eb03f6..06fb39406 100644 --- a/pina/model/block/message_passing/interaction_network_block.py +++ b/pina/_src/model/block/message_passing/interaction_network_block.py @@ -2,8 +2,8 @@ import torch from torch_geometric.nn import MessagePassing -from ....utils import check_positive_integer -from ....model import FeedForward +from pina._src.core.utils import check_positive_integer +from pina._src.model.feed_forward import FeedForward class InteractionNetworkBlock(MessagePassing): diff --git a/pina/model/block/message_passing/radial_field_network_block.py b/pina/_src/model/block/message_passing/radial_field_network_block.py similarity index 97% rename from pina/model/block/message_passing/radial_field_network_block.py rename to pina/_src/model/block/message_passing/radial_field_network_block.py index ef621b10e..ede0fb645 100644 --- a/pina/model/block/message_passing/radial_field_network_block.py +++ b/pina/_src/model/block/message_passing/radial_field_network_block.py @@ -3,8 +3,8 @@ import torch from torch_geometric.nn import MessagePassing from torch_geometric.utils import remove_self_loops -from ....utils import check_positive_integer -from ....model import FeedForward +from pina._src.core.utils import check_positive_integer +from pina._src.model.feed_forward import FeedForward class RadialFieldNetworkBlock(MessagePassing): diff --git a/pina/model/block/orthogonal.py b/pina/_src/model/block/orthogonal.py similarity index 98% rename from pina/model/block/orthogonal.py rename to pina/_src/model/block/orthogonal.py index cd45b3c72..24021ada6 100644 --- a/pina/model/block/orthogonal.py +++ b/pina/_src/model/block/orthogonal.py @@ -1,7 +1,7 @@ """Module for the Orthogonal Block class.""" import torch -from ...utils import check_consistency +from pina._src.core.utils import check_consistency class OrthogonalBlock(torch.nn.Module): diff --git a/pina/model/block/pirate_network_block.py b/pina/_src/model/block/pirate_network_block.py similarity index 97% rename from pina/model/block/pirate_network_block.py rename to pina/_src/model/block/pirate_network_block.py index cfeb8410e..752f81901 100644 --- a/pina/model/block/pirate_network_block.py +++ b/pina/_src/model/block/pirate_network_block.py @@ -1,7 +1,7 @@ """Module for the PirateNet block class.""" import torch -from ...utils import check_consistency, check_positive_integer +from pina._src.core.utils import check_consistency, check_positive_integer class PirateNetBlock(torch.nn.Module): diff --git a/pina/model/block/pod_block.py b/pina/_src/model/block/pod_block.py similarity index 100% rename from pina/model/block/pod_block.py rename to pina/_src/model/block/pod_block.py diff --git a/pina/model/block/rbf_block.py b/pina/_src/model/block/rbf_block.py similarity index 99% rename from pina/model/block/rbf_block.py rename to pina/_src/model/block/rbf_block.py index 8001381bc..061e43109 100644 --- a/pina/model/block/rbf_block.py +++ b/pina/_src/model/block/rbf_block.py @@ -4,7 +4,7 @@ import warnings from itertools import combinations_with_replacement import torch -from ...utils import check_consistency +from pina._src.core.utils import check_consistency def linear(r): diff --git a/pina/model/block/residual.py b/pina/_src/model/block/residual.py similarity index 98% rename from pina/model/block/residual.py rename to pina/_src/model/block/residual.py index f109ce03d..d1e8134cc 100644 --- a/pina/model/block/residual.py +++ b/pina/_src/model/block/residual.py @@ -2,7 +2,7 @@ import torch from torch import nn -from ...utils import check_consistency +from pina._src.core.utils import check_consistency class ResidualBlock(nn.Module): diff --git a/pina/model/block/spectral.py b/pina/_src/model/block/spectral.py similarity index 99% rename from pina/model/block/spectral.py rename to pina/_src/model/block/spectral.py index aae915a42..fd5f48f6a 100644 --- a/pina/model/block/spectral.py +++ b/pina/_src/model/block/spectral.py @@ -2,7 +2,7 @@ import torch from torch import nn -from ...utils import check_consistency +from pina._src.core.utils import check_consistency ######## 1D Spectral Convolution ########### diff --git a/pina/model/block/stride.py b/pina/_src/model/block/stride.py similarity index 98% rename from pina/model/block/stride.py rename to pina/_src/model/block/stride.py index 2a26faf07..e802cddc0 100644 --- a/pina/model/block/stride.py +++ b/pina/_src/model/block/stride.py @@ -5,7 +5,7 @@ class Stride: """ - Stride class for continous convolution. + Stride class for continuous convolution. """ def __init__(self, dict_): diff --git a/pina/model/block/utils_convolution.py b/pina/_src/model/block/utils_convolution.py similarity index 100% rename from pina/model/block/utils_convolution.py rename to pina/_src/model/block/utils_convolution.py diff --git a/pina/model/deeponet.py b/pina/_src/model/deeponet.py similarity index 99% rename from pina/model/deeponet.py rename to pina/_src/model/deeponet.py index c65f6b316..800f2acc3 100644 --- a/pina/model/deeponet.py +++ b/pina/_src/model/deeponet.py @@ -3,7 +3,7 @@ from functools import partial import torch from torch import nn -from ..utils import check_consistency, is_function +from pina._src.core.utils import check_consistency, is_function class MIONet(torch.nn.Module): diff --git a/pina/model/equivariant_graph_neural_operator.py b/pina/_src/model/equivariant_graph_neural_operator.py similarity index 97% rename from pina/model/equivariant_graph_neural_operator.py rename to pina/_src/model/equivariant_graph_neural_operator.py index 6b33df6db..3aa7dde69 100644 --- a/pina/model/equivariant_graph_neural_operator.py +++ b/pina/_src/model/equivariant_graph_neural_operator.py @@ -1,8 +1,10 @@ """Module for the Equivariant Graph Neural Operator model.""" import torch -from ..utils import check_positive_integer -from .block.message_passing import EquivariantGraphNeuralOperatorBlock +from pina._src.core.utils import check_positive_integer +from pina._src.model.block.message_passing.equivariant_graph_neural_operator_block import ( + EquivariantGraphNeuralOperatorBlock, +) class EquivariantGraphNeuralOperator(torch.nn.Module): diff --git a/pina/model/feed_forward.py b/pina/_src/model/feed_forward.py similarity index 99% rename from pina/model/feed_forward.py rename to pina/_src/model/feed_forward.py index a1651b38b..fdf6bc91e 100644 --- a/pina/model/feed_forward.py +++ b/pina/_src/model/feed_forward.py @@ -2,8 +2,8 @@ import torch from torch import nn -from ..utils import check_consistency -from .block.residual import EnhancedLinear +from pina._src.core.utils import check_consistency +from pina._src.model.block.residual import EnhancedLinear class FeedForward(torch.nn.Module): diff --git a/pina/model/fourier_neural_operator.py b/pina/_src/model/fourier_neural_operator.py similarity index 97% rename from pina/model/fourier_neural_operator.py rename to pina/_src/model/fourier_neural_operator.py index e1336c999..7517b39b4 100644 --- a/pina/model/fourier_neural_operator.py +++ b/pina/_src/model/fourier_neural_operator.py @@ -3,10 +3,14 @@ import warnings import torch from torch import nn -from ..label_tensor import LabelTensor -from ..utils import check_consistency -from .block.fourier_block import FourierBlock1D, FourierBlock2D, FourierBlock3D -from .kernel_neural_operator import KernelNeuralOperator +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency +from pina._src.model.block.fourier_block import ( + FourierBlock1D, + FourierBlock2D, + FourierBlock3D, +) +from pina._src.model.kernel_neural_operator import KernelNeuralOperator class FourierIntegralKernel(torch.nn.Module): diff --git a/pina/model/graph_neural_operator.py b/pina/_src/model/graph_neural_operator.py similarity index 98% rename from pina/model/graph_neural_operator.py rename to pina/_src/model/graph_neural_operator.py index 3cb5cdd31..e4d844fcb 100644 --- a/pina/model/graph_neural_operator.py +++ b/pina/_src/model/graph_neural_operator.py @@ -2,8 +2,8 @@ import torch from torch.nn import Tanh -from .block.gno_block import GNOBlock -from .kernel_neural_operator import KernelNeuralOperator +from pina._src.model.block.gno_block import GNOBlock +from pina._src.model.kernel_neural_operator import KernelNeuralOperator class GraphNeuralKernel(torch.nn.Module): diff --git a/pina/model/kernel_neural_operator.py b/pina/_src/model/kernel_neural_operator.py similarity index 99% rename from pina/model/kernel_neural_operator.py rename to pina/_src/model/kernel_neural_operator.py index e3cb790e5..81d1be45d 100644 --- a/pina/model/kernel_neural_operator.py +++ b/pina/_src/model/kernel_neural_operator.py @@ -1,7 +1,7 @@ """Module for the Kernel Neural Operator model class.""" import torch -from ..utils import check_consistency +from pina._src.core.utils import check_consistency class KernelNeuralOperator(torch.nn.Module): diff --git a/pina/model/low_rank_neural_operator.py b/pina/_src/model/low_rank_neural_operator.py similarity index 97% rename from pina/model/low_rank_neural_operator.py rename to pina/_src/model/low_rank_neural_operator.py index 1a7082dff..049894001 100644 --- a/pina/model/low_rank_neural_operator.py +++ b/pina/_src/model/low_rank_neural_operator.py @@ -3,10 +3,10 @@ import torch from torch import nn -from ..utils import check_consistency +from pina._src.core.utils import check_consistency -from .kernel_neural_operator import KernelNeuralOperator -from .block.low_rank_block import LowRankBlock +from pina._src.model.kernel_neural_operator import KernelNeuralOperator +from pina._src.model.block.low_rank_block import LowRankBlock class LowRankNeuralOperator(KernelNeuralOperator): diff --git a/pina/model/multi_feed_forward.py b/pina/_src/model/multi_feed_forward.py similarity index 95% rename from pina/model/multi_feed_forward.py rename to pina/_src/model/multi_feed_forward.py index f2f149ca6..df8fb19e2 100644 --- a/pina/model/multi_feed_forward.py +++ b/pina/_src/model/multi_feed_forward.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod import torch -from .feed_forward import FeedForward +from pina._src.model.feed_forward import FeedForward class MultiFeedForward(torch.nn.Module, ABC): diff --git a/pina/model/pirate_network.py b/pina/_src/model/pirate_network.py similarity index 95% rename from pina/model/pirate_network.py rename to pina/_src/model/pirate_network.py index 96102b41f..09aad269d 100644 --- a/pina/model/pirate_network.py +++ b/pina/_src/model/pirate_network.py @@ -1,8 +1,9 @@ """Module for the PirateNet model class.""" import torch -from .block import FourierFeatureEmbedding, PirateNetBlock -from ..utils import check_consistency, check_positive_integer +from pina._src.model.block.embedding import FourierFeatureEmbedding +from pina._src.model.block.pirate_network_block import PirateNetBlock +from pina._src.core.utils import check_consistency, check_positive_integer class PirateNet(torch.nn.Module): diff --git a/pina/model/sindy.py b/pina/_src/model/sindy.py similarity index 97% rename from pina/model/sindy.py rename to pina/_src/model/sindy.py index a40fa37b4..f69842a54 100644 --- a/pina/model/sindy.py +++ b/pina/_src/model/sindy.py @@ -2,7 +2,7 @@ from typing import Callable import torch -from ..utils import check_consistency, check_positive_integer +from pina._src.core.utils import check_consistency, check_positive_integer class SINDy(torch.nn.Module): diff --git a/pina/model/spline.py b/pina/_src/model/spline.py similarity index 99% rename from pina/model/spline.py rename to pina/_src/model/spline.py index d9141fe8c..5e5b133c3 100644 --- a/pina/model/spline.py +++ b/pina/_src/model/spline.py @@ -2,7 +2,7 @@ import warnings import torch -from ..utils import check_positive_integer, check_consistency +from pina._src.core.utils import check_consistency, check_positive_integer class Spline(torch.nn.Module): diff --git a/pina/model/spline_surface.py b/pina/_src/model/spline_surface.py similarity index 98% rename from pina/model/spline_surface.py rename to pina/_src/model/spline_surface.py index 767e5b0dc..d54a0c7bb 100644 --- a/pina/model/spline_surface.py +++ b/pina/_src/model/spline_surface.py @@ -2,8 +2,8 @@ import torch from .spline import Spline -from ..label_tensor import LabelTensor -from ..utils import check_consistency, check_positive_integer +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import check_consistency, check_positive_integer class SplineSurface(torch.nn.Module): diff --git a/pina/_src/optim/__init__.py b/pina/_src/optim/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/optim/optimizer_interface.py b/pina/_src/optim/optimizer_interface.py similarity index 100% rename from pina/optim/optimizer_interface.py rename to pina/_src/optim/optimizer_interface.py diff --git a/pina/optim/scheduler_interface.py b/pina/_src/optim/scheduler_interface.py similarity index 100% rename from pina/optim/scheduler_interface.py rename to pina/_src/optim/scheduler_interface.py diff --git a/pina/optim/torch_optimizer.py b/pina/_src/optim/torch_optimizer.py similarity index 92% rename from pina/optim/torch_optimizer.py rename to pina/_src/optim/torch_optimizer.py index 7163c295e..f01d3b3cb 100644 --- a/pina/optim/torch_optimizer.py +++ b/pina/_src/optim/torch_optimizer.py @@ -2,8 +2,8 @@ import torch -from ..utils import check_consistency -from .optimizer_interface import Optimizer +from pina._src.core.utils import check_consistency +from pina._src.optim.optimizer_interface import Optimizer class TorchOptimizer(Optimizer): diff --git a/pina/optim/torch_scheduler.py b/pina/_src/optim/torch_scheduler.py similarity index 90% rename from pina/optim/torch_scheduler.py rename to pina/_src/optim/torch_scheduler.py index ff12300a1..bf9927836 100644 --- a/pina/optim/torch_scheduler.py +++ b/pina/_src/optim/torch_scheduler.py @@ -7,9 +7,9 @@ _LRScheduler as LRScheduler, ) # torch < 2.0 -from ..utils import check_consistency -from .optimizer_interface import Optimizer -from .scheduler_interface import Scheduler +from pina._src.core.utils import check_consistency +from pina._src.optim.optimizer_interface import Optimizer +from pina._src.optim.scheduler_interface import Scheduler class TorchScheduler(Scheduler): diff --git a/pina/_src/problem/__init__.py b/pina/_src/problem/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/problem/abstract_problem.py b/pina/_src/problem/abstract_problem.py similarity index 96% rename from pina/problem/abstract_problem.py rename to pina/_src/problem/abstract_problem.py index 441356def..381186e00 100644 --- a/pina/problem/abstract_problem.py +++ b/pina/_src/problem/abstract_problem.py @@ -3,11 +3,14 @@ from abc import ABCMeta, abstractmethod import warnings from copy import deepcopy -from ..utils import check_consistency -from ..domain import DomainInterface, CartesianDomain -from ..condition.domain_equation_condition import DomainEquationCondition -from ..label_tensor import LabelTensor -from ..utils import merge_tensors, custom_warning_format +from pina._src.core.utils import check_consistency +from pina._src.domain.domain_interface import DomainInterface +from pina._src.domain.cartesian_domain import CartesianDomain +from pina._src.condition.domain_equation_condition import ( + DomainEquationCondition, +) +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.utils import merge_tensors, custom_warning_format class AbstractProblem(metaclass=ABCMeta): @@ -58,15 +61,10 @@ def collected_data(self): if not self.are_all_domains_discretised: warnings.formatwarning = custom_warning_format warnings.filterwarnings("always", category=RuntimeWarning) - warning_message = "\n".join( - [ - f"""{" " * 13} ---> Domain {key} { + warning_message = "\n".join([f"""{" " * 13} ---> Domain {key} { "sampled" if key in self.discretised_domains else - "not sampled"}""" - for key in self.domains - ] - ) + "not sampled"}""" for key in self.domains]) warnings.warn( "Some of the domains are still not sampled. Consider calling " "problem.discretise_domain function for all domains before " diff --git a/pina/problem/inverse_problem.py b/pina/_src/problem/inverse_problem.py similarity index 96% rename from pina/problem/inverse_problem.py rename to pina/_src/problem/inverse_problem.py index 8a2902448..fa2f3d57f 100644 --- a/pina/problem/inverse_problem.py +++ b/pina/_src/problem/inverse_problem.py @@ -2,7 +2,7 @@ from abc import abstractmethod import torch -from .abstract_problem import AbstractProblem +from pina._src.problem.abstract_problem import AbstractProblem class InverseProblem(AbstractProblem): diff --git a/pina/problem/parametric_problem.py b/pina/_src/problem/parametric_problem.py similarity index 100% rename from pina/problem/parametric_problem.py rename to pina/_src/problem/parametric_problem.py diff --git a/pina/problem/spatial_problem.py b/pina/_src/problem/spatial_problem.py similarity index 100% rename from pina/problem/spatial_problem.py rename to pina/_src/problem/spatial_problem.py diff --git a/pina/problem/time_dependent_problem.py b/pina/_src/problem/time_dependent_problem.py similarity index 100% rename from pina/problem/time_dependent_problem.py rename to pina/_src/problem/time_dependent_problem.py diff --git a/pina/_src/problem/zoo/__init__.py b/pina/_src/problem/zoo/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/problem/zoo/acoustic_wave.py b/pina/_src/problem/zoo/acoustic_wave.py similarity index 85% rename from pina/problem/zoo/acoustic_wave.py rename to pina/_src/problem/zoo/acoustic_wave.py index b4b2035a4..44db8eb96 100644 --- a/pina/problem/zoo/acoustic_wave.py +++ b/pina/_src/problem/zoo/acoustic_wave.py @@ -1,13 +1,14 @@ """Formulation of the acoustic wave problem.""" import torch -from ... import Condition -from ...problem import SpatialProblem, TimeDependentProblem -from ...utils import check_consistency -from ...domain import CartesianDomain -from ...equation import ( - Equation, - SystemEquation, +from pina._src.condition.condition import Condition +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.problem.time_dependent_problem import TimeDependentProblem +from pina._src.core.utils import check_consistency +from pina._src.domain.cartesian_domain import CartesianDomain +from pina._src.equation.equation import Equation +from pina._src.equation.system_equation import SystemEquation +from pina._src.equation.equation_factory import ( FixedValue, FixedGradient, AcousticWave, diff --git a/pina/problem/zoo/advection.py b/pina/_src/problem/zoo/advection.py similarity index 84% rename from pina/problem/zoo/advection.py rename to pina/_src/problem/zoo/advection.py index c709b9632..3067ce8bf 100644 --- a/pina/problem/zoo/advection.py +++ b/pina/_src/problem/zoo/advection.py @@ -1,11 +1,13 @@ """Formulation of the advection problem.""" import torch -from ... import Condition -from ...problem import SpatialProblem, TimeDependentProblem -from ...equation import Equation, Advection -from ...utils import check_consistency -from ...domain import CartesianDomain +from pina._src.condition.condition import Condition +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.problem.time_dependent_problem import TimeDependentProblem +from pina._src.equation.equation import Equation +from pina._src.equation.equation_factory import Advection +from pina._src.core.utils import check_consistency +from pina._src.domain.cartesian_domain import CartesianDomain def initial_condition(input_, output_): diff --git a/pina/problem/zoo/allen_cahn.py b/pina/_src/problem/zoo/allen_cahn.py similarity index 84% rename from pina/problem/zoo/allen_cahn.py rename to pina/_src/problem/zoo/allen_cahn.py index 900d5cf33..125a10304 100644 --- a/pina/problem/zoo/allen_cahn.py +++ b/pina/_src/problem/zoo/allen_cahn.py @@ -1,11 +1,14 @@ """Formulation of the Allen Cahn problem.""" import torch -from ... import Condition -from ...problem import SpatialProblem, TimeDependentProblem -from ...equation import Equation, AllenCahn -from ...utils import check_consistency -from ...domain import CartesianDomain + +from pina._src.condition.condition import Condition +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.problem.time_dependent_problem import TimeDependentProblem +from pina._src.equation.equation import Equation +from pina._src.equation.equation_factory import AllenCahn +from pina._src.core.utils import check_consistency +from pina._src.domain.cartesian_domain import CartesianDomain def initial_condition(input_, output_): diff --git a/pina/problem/zoo/diffusion_reaction.py b/pina/_src/problem/zoo/diffusion_reaction.py similarity index 88% rename from pina/problem/zoo/diffusion_reaction.py rename to pina/_src/problem/zoo/diffusion_reaction.py index fd02b8368..443ff49c5 100644 --- a/pina/problem/zoo/diffusion_reaction.py +++ b/pina/_src/problem/zoo/diffusion_reaction.py @@ -1,11 +1,13 @@ """Formulation of the diffusion-reaction problem.""" import torch -from ... import Condition -from ...equation import Equation, FixedValue, DiffusionReaction -from ...problem import SpatialProblem, TimeDependentProblem -from ...utils import check_consistency -from ...domain import CartesianDomain +from pina._src.condition.condition import Condition +from pina._src.equation.equation import Equation +from pina._src.equation.equation_factory import FixedValue, DiffusionReaction +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.problem.time_dependent_problem import TimeDependentProblem +from pina._src.core.utils import check_consistency +from pina._src.domain.cartesian_domain import CartesianDomain def initial_condition(input_, output_): diff --git a/pina/problem/zoo/helmholtz.py b/pina/_src/problem/zoo/helmholtz.py similarity index 87% rename from pina/problem/zoo/helmholtz.py rename to pina/_src/problem/zoo/helmholtz.py index f7f288627..f59bfdf1e 100644 --- a/pina/problem/zoo/helmholtz.py +++ b/pina/_src/problem/zoo/helmholtz.py @@ -1,11 +1,12 @@ """Formulation of the Helmholtz problem.""" import torch -from ... import Condition -from ...equation import FixedValue, Helmholtz -from ...utils import check_consistency -from ...domain import CartesianDomain -from ...problem import SpatialProblem + +from pina._src.condition.condition import Condition +from pina._src.equation.equation_factory import FixedValue, Helmholtz +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.core.utils import check_consistency +from pina._src.domain.cartesian_domain import CartesianDomain class HelmholtzProblem(SpatialProblem): diff --git a/pina/problem/zoo/inverse_poisson_2d_square.py b/pina/_src/problem/zoo/inverse_poisson_2d_square.py similarity index 90% rename from pina/problem/zoo/inverse_poisson_2d_square.py rename to pina/_src/problem/zoo/inverse_poisson_2d_square.py index 17f30ae14..19628cae0 100644 --- a/pina/problem/zoo/inverse_poisson_2d_square.py +++ b/pina/_src/problem/zoo/inverse_poisson_2d_square.py @@ -4,13 +4,17 @@ import requests import torch from io import BytesIO -from ... import Condition -from ... import LabelTensor -from ...operator import laplacian -from ...domain import CartesianDomain -from ...equation import Equation, FixedValue -from ...problem import SpatialProblem, InverseProblem -from ...utils import custom_warning_format, check_consistency + + +from pina._src.condition.condition import Condition +from pina._src.equation.equation import Equation +from pina._src.equation.equation_factory import FixedValue +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.problem.inverse_problem import InverseProblem +from pina._src.domain.cartesian_domain import CartesianDomain +from pina._src.core.label_tensor import LabelTensor +from pina._src.core.operator import laplacian +from pina._src.core.utils import custom_warning_format, check_consistency warnings.formatwarning = custom_warning_format warnings.filterwarnings("always", category=ResourceWarning) diff --git a/pina/problem/zoo/poisson_2d_square.py b/pina/_src/problem/zoo/poisson_2d_square.py similarity index 86% rename from pina/problem/zoo/poisson_2d_square.py rename to pina/_src/problem/zoo/poisson_2d_square.py index 5de38b301..12b365666 100644 --- a/pina/problem/zoo/poisson_2d_square.py +++ b/pina/_src/problem/zoo/poisson_2d_square.py @@ -1,10 +1,11 @@ """Formulation of the Poisson problem in a square domain.""" import torch -from ...equation import FixedValue, Poisson -from ...problem import SpatialProblem -from ...domain import CartesianDomain -from ... import Condition + +from pina._src.condition.condition import Condition +from pina._src.equation.equation_factory import FixedValue, Poisson +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.domain.cartesian_domain import CartesianDomain def forcing_term(input_): diff --git a/pina/problem/zoo/supervised_problem.py b/pina/_src/problem/zoo/supervised_problem.py similarity index 93% rename from pina/problem/zoo/supervised_problem.py rename to pina/_src/problem/zoo/supervised_problem.py index 61a49c0cb..81fb18a44 100644 --- a/pina/problem/zoo/supervised_problem.py +++ b/pina/_src/problem/zoo/supervised_problem.py @@ -1,7 +1,7 @@ """Formulation of a Supervised Problem in PINA.""" -from ..abstract_problem import AbstractProblem -from ... import Condition +from pina._src.problem.abstract_problem import AbstractProblem +from pina._src.condition.condition import Condition class SupervisedProblem(AbstractProblem): diff --git a/pina/_src/solver/__init__.py b/pina/_src/solver/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/_src/solver/ensemble_solver/__init__.py b/pina/_src/solver/ensemble_solver/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/solver/ensemble_solver/ensemble_pinn.py b/pina/_src/solver/ensemble_solver/ensemble_pinn.py similarity index 96% rename from pina/solver/ensemble_solver/ensemble_pinn.py rename to pina/_src/solver/ensemble_solver/ensemble_pinn.py index 33d929ad2..f010753ec 100644 --- a/pina/solver/ensemble_solver/ensemble_pinn.py +++ b/pina/_src/solver/ensemble_solver/ensemble_pinn.py @@ -2,9 +2,13 @@ import torch -from .ensemble_solver_interface import DeepEnsembleSolverInterface -from ..physics_informed_solver import PINNInterface -from ...problem import InverseProblem +from pina._src.solver.ensemble_solver.ensemble_solver_interface import ( + DeepEnsembleSolverInterface, +) +from pina._src.solver.physics_informed_solver.pinn_interface import ( + PINNInterface, +) +from pina._src.problem.inverse_problem import InverseProblem class DeepEnsemblePINN(PINNInterface, DeepEnsembleSolverInterface): diff --git a/pina/solver/ensemble_solver/ensemble_solver_interface.py b/pina/_src/solver/ensemble_solver/ensemble_solver_interface.py similarity index 98% rename from pina/solver/ensemble_solver/ensemble_solver_interface.py rename to pina/_src/solver/ensemble_solver/ensemble_solver_interface.py index 6d874e1bf..7b87e28f1 100644 --- a/pina/solver/ensemble_solver/ensemble_solver_interface.py +++ b/pina/_src/solver/ensemble_solver/ensemble_solver_interface.py @@ -1,8 +1,8 @@ """Module for the DeepEnsemble solver interface.""" import torch -from ..solver import MultiSolverInterface -from ...utils import check_consistency +from pina._src.solver.solver import MultiSolverInterface +from pina._src.core.utils import check_consistency class DeepEnsembleSolverInterface(MultiSolverInterface): diff --git a/pina/solver/ensemble_solver/ensemble_supervised.py b/pina/_src/solver/ensemble_solver/ensemble_supervised.py similarity index 95% rename from pina/solver/ensemble_solver/ensemble_supervised.py rename to pina/_src/solver/ensemble_solver/ensemble_supervised.py index e4837ccdb..ea6f7edde 100644 --- a/pina/solver/ensemble_solver/ensemble_supervised.py +++ b/pina/_src/solver/ensemble_solver/ensemble_supervised.py @@ -1,7 +1,11 @@ """Module for the DeepEnsemble supervised solver.""" -from .ensemble_solver_interface import DeepEnsembleSolverInterface -from ..supervised_solver import SupervisedSolverInterface +from pina._src.solver.ensemble_solver.ensemble_solver_interface import ( + DeepEnsembleSolverInterface, +) +from pina._src.solver.supervised_solver.supervised_solver_interface import ( + SupervisedSolverInterface, +) class DeepEnsembleSupervisedSolver( diff --git a/pina/solver/garom.py b/pina/_src/solver/garom.py similarity index 97% rename from pina/solver/garom.py rename to pina/_src/solver/garom.py index 372eeddfa..3f499abd1 100644 --- a/pina/solver/garom.py +++ b/pina/_src/solver/garom.py @@ -2,10 +2,11 @@ import torch from torch.nn.modules.loss import _Loss -from .solver import MultiSolverInterface -from ..condition import InputTargetCondition -from ..utils import check_consistency -from ..loss import LossInterface, PowerLoss +from pina._src.solver.solver import MultiSolverInterface +from pina._src.condition.input_target_condition import InputTargetCondition +from pina._src.core.utils import check_consistency +from pina._src.loss.loss_interface import LossInterface +from pina._src.loss.power_loss import PowerLoss class GAROM(MultiSolverInterface): diff --git a/pina/_src/solver/physics_informed_solver/__init__.py b/pina/_src/solver/physics_informed_solver/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/solver/physics_informed_solver/causal_pinn.py b/pina/_src/solver/physics_informed_solver/causal_pinn.py similarity index 97% rename from pina/solver/physics_informed_solver/causal_pinn.py rename to pina/_src/solver/physics_informed_solver/causal_pinn.py index ab085be2d..e7e97392b 100644 --- a/pina/solver/physics_informed_solver/causal_pinn.py +++ b/pina/_src/solver/physics_informed_solver/causal_pinn.py @@ -2,9 +2,9 @@ import torch -from ...problem import TimeDependentProblem -from .pinn import PINN -from ...utils import check_consistency +from pina._src.problem.time_dependent_problem import TimeDependentProblem +from pina._src.solver.physics_informed_solver.pinn import PINN +from pina._src.core.utils import check_consistency class CausalPINN(PINN): diff --git a/pina/solver/physics_informed_solver/competitive_pinn.py b/pina/_src/solver/physics_informed_solver/competitive_pinn.py similarity index 97% rename from pina/solver/physics_informed_solver/competitive_pinn.py rename to pina/_src/solver/physics_informed_solver/competitive_pinn.py index 5375efba1..287e0fd8d 100644 --- a/pina/solver/physics_informed_solver/competitive_pinn.py +++ b/pina/_src/solver/physics_informed_solver/competitive_pinn.py @@ -3,9 +3,11 @@ import copy import torch -from ...problem import InverseProblem -from .pinn_interface import PINNInterface -from ..solver import MultiSolverInterface +from pina._src.problem.inverse_problem import InverseProblem +from pina._src.solver.physics_informed_solver.pinn_interface import ( + PINNInterface, +) +from pina._src.solver.solver import MultiSolverInterface class CompetitivePINN(PINNInterface, MultiSolverInterface): diff --git a/pina/solver/physics_informed_solver/gradient_pinn.py b/pina/_src/solver/physics_informed_solver/gradient_pinn.py similarity index 96% rename from pina/solver/physics_informed_solver/gradient_pinn.py rename to pina/_src/solver/physics_informed_solver/gradient_pinn.py index 0de431c41..9583c3025 100644 --- a/pina/solver/physics_informed_solver/gradient_pinn.py +++ b/pina/_src/solver/physics_informed_solver/gradient_pinn.py @@ -2,9 +2,9 @@ import torch -from .pinn import PINN -from ...operator import grad -from ...problem import SpatialProblem +from pina._src.solver.physics_informed_solver.pinn import PINN +from pina._src.core.operator import grad +from pina._src.problem.spatial_problem import SpatialProblem class GradientPINN(PINN): diff --git a/pina/solver/physics_informed_solver/pinn.py b/pina/_src/solver/physics_informed_solver/pinn.py similarity index 95% rename from pina/solver/physics_informed_solver/pinn.py rename to pina/_src/solver/physics_informed_solver/pinn.py index 914d01451..dbea8cbe3 100644 --- a/pina/solver/physics_informed_solver/pinn.py +++ b/pina/_src/solver/physics_informed_solver/pinn.py @@ -2,9 +2,11 @@ import torch -from .pinn_interface import PINNInterface -from ..solver import SingleSolverInterface -from ...problem import InverseProblem +from pina._src.solver.physics_informed_solver.pinn_interface import ( + PINNInterface, +) +from pina._src.solver.solver import SingleSolverInterface +from pina._src.problem.inverse_problem import InverseProblem class PINN(PINNInterface, SingleSolverInterface): diff --git a/pina/solver/physics_informed_solver/pinn_interface.py b/pina/_src/solver/physics_informed_solver/pinn_interface.py similarity index 95% rename from pina/solver/physics_informed_solver/pinn_interface.py rename to pina/_src/solver/physics_informed_solver/pinn_interface.py index 65a0dd78f..517b48082 100644 --- a/pina/solver/physics_informed_solver/pinn_interface.py +++ b/pina/_src/solver/physics_informed_solver/pinn_interface.py @@ -4,11 +4,13 @@ import warnings import torch -from ...utils import custom_warning_format -from ..supervised_solver import SupervisedSolverInterface -from ...condition import ( - InputTargetCondition, - InputEquationCondition, +from pina._src.core.utils import custom_warning_format +from pina._src.solver.supervised_solver.supervised_solver_interface import ( + SupervisedSolverInterface, +) +from pina._src.condition.input_target_condition import InputTargetCondition +from pina._src.condition.input_equation_condition import InputEquationCondition +from pina._src.condition.domain_equation_condition import ( DomainEquationCondition, ) diff --git a/pina/solver/physics_informed_solver/rba_pinn.py b/pina/_src/solver/physics_informed_solver/rba_pinn.py similarity index 99% rename from pina/solver/physics_informed_solver/rba_pinn.py rename to pina/_src/solver/physics_informed_solver/rba_pinn.py index 5c8d50fed..7e7deda0a 100644 --- a/pina/solver/physics_informed_solver/rba_pinn.py +++ b/pina/_src/solver/physics_informed_solver/rba_pinn.py @@ -2,8 +2,8 @@ import torch -from .pinn import PINN -from ...utils import check_consistency +from pina._src.solver.physics_informed_solver.pinn import PINN +from pina._src.core.utils import check_consistency class RBAPINN(PINN): diff --git a/pina/solver/physics_informed_solver/self_adaptive_pinn.py b/pina/_src/solver/physics_informed_solver/self_adaptive_pinn.py similarity index 98% rename from pina/solver/physics_informed_solver/self_adaptive_pinn.py rename to pina/_src/solver/physics_informed_solver/self_adaptive_pinn.py index b1d2a2cb4..ee7f281e6 100644 --- a/pina/solver/physics_informed_solver/self_adaptive_pinn.py +++ b/pina/_src/solver/physics_informed_solver/self_adaptive_pinn.py @@ -1,12 +1,13 @@ """Module for the Self-Adaptive PINN solver.""" -from copy import deepcopy import torch -from ...utils import check_consistency -from ...problem import InverseProblem -from ..solver import MultiSolverInterface -from .pinn_interface import PINNInterface +from pina._src.core.utils import check_consistency +from pina._src.problem.inverse_problem import InverseProblem +from pina._src.solver.solver import MultiSolverInterface +from pina._src.solver.physics_informed_solver.pinn_interface import ( + PINNInterface, +) class Weights(torch.nn.Module): diff --git a/pina/solver/solver.py b/pina/_src/solver/solver.py similarity index 97% rename from pina/solver/solver.py rename to pina/_src/solver/solver.py index 57a28a8a7..d6abd493b 100644 --- a/pina/solver/solver.py +++ b/pina/_src/solver/solver.py @@ -5,11 +5,15 @@ import torch from torch._dynamo import OptimizedModule -from ..problem import AbstractProblem, InverseProblem -from ..optim import Optimizer, Scheduler, TorchOptimizer, TorchScheduler -from ..loss import WeightingInterface -from ..loss.scalar_weighting import _NoWeighting -from ..utils import check_consistency, labelize_forward +from pina._src.problem.abstract_problem import AbstractProblem +from pina._src.problem.inverse_problem import InverseProblem +from pina._src.optim.optimizer_interface import Optimizer +from pina._src.optim.scheduler_interface import Scheduler +from pina._src.optim.torch_optimizer import TorchOptimizer +from pina._src.optim.torch_scheduler import TorchScheduler +from pina._src.loss.weighting_interface import WeightingInterface +from pina._src.loss.scalar_weighting import _NoWeighting +from pina._src.core.utils import check_consistency, labelize_forward class SolverInterface(lightning.pytorch.LightningModule, metaclass=ABCMeta): diff --git a/pina/_src/solver/supervised_solver/__init__.py b/pina/_src/solver/supervised_solver/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pina/solver/supervised_solver/reduced_order_model.py b/pina/_src/solver/supervised_solver/reduced_order_model.py similarity index 97% rename from pina/solver/supervised_solver/reduced_order_model.py rename to pina/_src/solver/supervised_solver/reduced_order_model.py index 727f438e2..d9830d766 100644 --- a/pina/solver/supervised_solver/reduced_order_model.py +++ b/pina/_src/solver/supervised_solver/reduced_order_model.py @@ -1,8 +1,10 @@ """Module for the Reduced Order Model solver""" import torch -from .supervised_solver_interface import SupervisedSolverInterface -from ..solver import SingleSolverInterface +from pina._src.solver.supervised_solver.supervised_solver_interface import ( + SupervisedSolverInterface, +) +from pina._src.solver.solver import SingleSolverInterface class ReducedOrderModelSolver(SupervisedSolverInterface, SingleSolverInterface): diff --git a/pina/solver/supervised_solver/supervised.py b/pina/_src/solver/supervised_solver/supervised.py similarity index 95% rename from pina/solver/supervised_solver/supervised.py rename to pina/_src/solver/supervised_solver/supervised.py index 70cd8fe4b..65d438c01 100644 --- a/pina/solver/supervised_solver/supervised.py +++ b/pina/_src/solver/supervised_solver/supervised.py @@ -1,7 +1,9 @@ """Module for the Supervised solver.""" -from .supervised_solver_interface import SupervisedSolverInterface -from ..solver import SingleSolverInterface +from pina._src.solver.supervised_solver.supervised_solver_interface import ( + SupervisedSolverInterface, +) +from pina._src.solver.solver import SingleSolverInterface class SupervisedSolver(SupervisedSolverInterface, SingleSolverInterface): diff --git a/pina/solver/supervised_solver/supervised_solver_interface.py b/pina/_src/solver/supervised_solver/supervised_solver_interface.py similarity index 92% rename from pina/solver/supervised_solver/supervised_solver_interface.py rename to pina/_src/solver/supervised_solver/supervised_solver_interface.py index 97070ce8f..030fc3f82 100644 --- a/pina/solver/supervised_solver/supervised_solver_interface.py +++ b/pina/_src/solver/supervised_solver/supervised_solver_interface.py @@ -5,10 +5,10 @@ import torch from torch.nn.modules.loss import _Loss -from ..solver import SolverInterface -from ...utils import check_consistency -from ...loss.loss_interface import LossInterface -from ...condition import InputTargetCondition +from pina._src.solver.solver import SolverInterface +from pina._src.core.utils import check_consistency +from pina._src.loss.loss_interface import LossInterface +from pina._src.condition.input_target_condition import InputTargetCondition class SupervisedSolverInterface(SolverInterface): diff --git a/pina/adaptive_function/__init__.py b/pina/adaptive_function/__init__.py index d53c5f368..9047be94a 100644 --- a/pina/adaptive_function/__init__.py +++ b/pina/adaptive_function/__init__.py @@ -1,4 +1,10 @@ -"""Adaptive Activation Functions Module.""" +"""Adaptive activation functions with learnable parameters. + +This module provides implementations of standard activation functions (ReLU, +SiLU, Tanh, etc.) augmented with trainable weights, as well as specialized +functions like SIREN, designed to improve convergence in PINNs and Neural +Operators. +""" __all__ = [ "AdaptiveActivationFunctionInterface", @@ -16,7 +22,7 @@ "AdaptiveExp", ] -from .adaptive_function import ( +from pina._src.adaptive_function.adaptive_function import ( AdaptiveReLU, AdaptiveSigmoid, AdaptiveTanh, @@ -30,4 +36,6 @@ AdaptiveSIREN, AdaptiveExp, ) -from .adaptive_function_interface import AdaptiveActivationFunctionInterface +from pina._src.adaptive_function.adaptive_function_interface import ( + AdaptiveActivationFunctionInterface, +) diff --git a/pina/callback/__init__.py b/pina/callback/__init__.py index 92da661cb..2f6d5a0a2 100644 --- a/pina/callback/__init__.py +++ b/pina/callback/__init__.py @@ -1,4 +1,9 @@ -"""Module for the Pina Callbacks.""" +"""Training callbacks for PINA lifecycle management. + +This module provides specialized callbacks for training Scientific Machine +Learning models, including adaptive sample refinement (R3), optimizer +switching logic, and data normalization utilities. +""" __all__ = [ "SwitchOptimizer", @@ -9,9 +14,11 @@ "R3Refinement", ] -from .optim.switch_optimizer import SwitchOptimizer -from .optim.switch_scheduler import SwitchScheduler -from .processing.normalizer_data_callback import NormalizerDataCallback -from .processing.pina_progress_bar import PINAProgressBar -from .processing.metric_tracker import MetricTracker -from .refinement import R3Refinement +from pina._src.callback.optim.switch_optimizer import SwitchOptimizer +from pina._src.callback.optim.switch_scheduler import SwitchScheduler +from pina._src.callback.processing.normalizer_data_callback import ( + NormalizerDataCallback, +) +from pina._src.callback.processing.pina_progress_bar import PINAProgressBar +from pina._src.callback.processing.metric_tracker import MetricTracker +from pina._src.callback.refinement.r3_refinement import R3Refinement diff --git a/pina/callback/refinement/__init__.py b/pina/callback/refinement/__init__.py deleted file mode 100644 index 396fcabaa..000000000 --- a/pina/callback/refinement/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -""" -Module for Pina Refinement callbacks. -""" - -__all__ = [ - "RefinementInterface", - "R3Refinement", -] - -from .refinement_interface import RefinementInterface -from .r3_refinement import R3Refinement diff --git a/pina/condition/__init__.py b/pina/condition/__init__.py index 4e57811fb..696567fa8 100644 --- a/pina/condition/__init__.py +++ b/pina/condition/__init__.py @@ -1,4 +1,10 @@ -"""Module for PINA Conditions classes.""" +"""Conditions for defining physics and data constraints. + +This module provides the interface and implementations for binding mathematical +equations, experimental data, and neural network targets to specific spatial +domains or graph structures. It supports various input-target mappings including +tensor-based, graph-based, and equation-based constraints. +""" __all__ = [ "Condition", @@ -17,22 +23,24 @@ "TensorDataCondition", ] -from .condition_interface import ConditionInterface -from .condition import Condition -from .domain_equation_condition import DomainEquationCondition -from .input_target_condition import ( +from pina._src.condition.condition_interface import ConditionInterface +from pina._src.condition.condition import Condition +from pina._src.condition.domain_equation_condition import ( + DomainEquationCondition, +) +from pina._src.condition.input_target_condition import ( InputTargetCondition, TensorInputTensorTargetCondition, TensorInputGraphTargetCondition, GraphInputTensorTargetCondition, GraphInputGraphTargetCondition, ) -from .input_equation_condition import ( +from pina._src.condition.input_equation_condition import ( InputEquationCondition, InputTensorEquationCondition, InputGraphEquationCondition, ) -from .data_condition import ( +from pina._src.condition.data_condition import ( DataCondition, GraphDataCondition, TensorDataCondition, diff --git a/pina/data/__init__.py b/pina/data/__init__.py index 70e100011..2ecebecdd 100644 --- a/pina/data/__init__.py +++ b/pina/data/__init__.py @@ -1,7 +1,32 @@ -"""Module for data, data module, and dataset.""" +"""Data management utilities for PINA. -__all__ = ["PinaDataModule", "PinaDataset"] +This module provides specialized Dataset and DataModule implementations +designed to handle physical coordinates, experimental observations, and +graph-structured data within the PINA training pipeline. +""" +from pina._src.data.data_module import ( + PinaDataModule, + PinaSampler, + DummyDataloader, + Collator, + PinaSampler, +) -from .data_module import PinaDataModule -from .dataset import PinaDataset +from pina._src.data.dataset import ( + PinaDataset, + PinaTensorDataset, + PinaGraphDataset, + PinaDatasetFactory, +) + +__all__ = [ + "PinaDataModule", + "PinaDataset", + "PinaSampler", + "DummyDataloader", + "Collator", + "PinaTensorDataset", + "PinaGraphDataset", + "PinaDatasetFactory", +] diff --git a/pina/domain/__init__.py b/pina/domain/__init__.py index 57999f4d8..6782563db 100644 --- a/pina/domain/__init__.py +++ b/pina/domain/__init__.py @@ -1,4 +1,9 @@ -"""Module to create and handle domains.""" +"""Geometry and domain definitions for spatial sampling. + +This module provides tools for defining the physical space of a problem, +including primitive shapes (Cartesian, Ellipsoid, Simplex) and set-theoretic +operations (Union, Intersection, etc.) for building complex geometries. +""" __all__ = [ "DomainInterface", @@ -13,13 +18,13 @@ "Exclusion", ] -from .domain_interface import DomainInterface -from .base_domain import BaseDomain -from .cartesian_domain import CartesianDomain -from .ellipsoid_domain import EllipsoidDomain -from .simplex_domain import SimplexDomain -from .operation_interface import OperationInterface -from .union import Union -from .intersection import Intersection -from .difference import Difference -from .exclusion import Exclusion +from pina._src.domain.domain_interface import DomainInterface +from pina._src.domain.base_domain import BaseDomain +from pina._src.domain.cartesian_domain import CartesianDomain +from pina._src.domain.ellipsoid_domain import EllipsoidDomain +from pina._src.domain.simplex_domain import SimplexDomain +from pina._src.domain.operation_interface import OperationInterface +from pina._src.domain.union import Union +from pina._src.domain.intersection import Intersection +from pina._src.domain.difference import Difference +from pina._src.domain.exclusion import Exclusion diff --git a/pina/equation/__init__.py b/pina/equation/__init__.py index 87a33554b..551099af6 100644 --- a/pina/equation/__init__.py +++ b/pina/equation/__init__.py @@ -1,4 +1,10 @@ -"""Module to define equations and systems of equations.""" +"""Mathematical equations and physical laws. + +This module provides a framework for defining differential equations, +boundary conditions, and complex systems of equations. It includes +pre-defined physical models such as Poisson, Laplace, and Wave equations, +along with factories for common derivative-based constraints. +""" __all__ = [ "SystemEquation", @@ -16,8 +22,8 @@ "AcousticWave", ] -from .equation import Equation -from .equation_factory import ( +from pina._src.equation.equation import Equation +from pina._src.equation.equation_factory import ( FixedFlux, FixedGradient, FixedLaplacian, @@ -30,4 +36,4 @@ Poisson, AcousticWave, ) -from .system_equation import SystemEquation +from pina._src.equation.system_equation import SystemEquation diff --git a/pina/graph.py b/pina/graph.py index 201f37a24..04c6374f5 100644 --- a/pina/graph.py +++ b/pina/graph.py @@ -1,421 +1,13 @@ -"""Module to build Graph objects and perform operations on them.""" +"""Public API for Graph connectivity and neighborhood logic. -import torch -from torch_geometric.data import Data, Batch -from torch_geometric.utils import to_undirected -from torch_geometric.utils.loop import remove_self_loops -from .label_tensor import LabelTensor -from .utils import check_consistency, is_function +This module exposes core graph types used to define spatial relationships +between points, such as fixed-radius and k-nearest neighbor (KNN) structures. +""" +from pina._src.core.graph import Graph, RadiusGraph, KNNGraph -class Graph(Data): - """ - Extends :class:`~torch_geometric.data.Data` class to include additional - checks and functionlities. - """ - - def __new__( - cls, - **kwargs, - ): - """ - Create a new instance of the :class:`~pina.graph.Graph` class by - checking the consistency of the input data and storing the attributes. - - :param dict kwargs: Parameters used to initialize the - :class:`~pina.graph.Graph` object. - :return: A new instance of the :class:`~pina.graph.Graph` class. - :rtype: Graph - """ - # create class instance - instance = Data.__new__(cls) - - # check the consistency of types defined in __init__, the others are not - # checked (as in pyg Data object) - instance._check_type_consistency(**kwargs) - - return instance - - def __init__( - self, - x=None, - edge_index=None, - pos=None, - edge_attr=None, - undirected=False, - **kwargs, - ): - """ - Initialize the object by setting the node features, edge index, - edge attributes, and positions. The edge index is preprocessed to make - the graph undirected if required. For more details, see the - :meth:`torch_geometric.data.Data` - - :param x: Optional tensor of node features ``(N, F)`` where ``F`` is the - number of features per node. - :type x: torch.Tensor, LabelTensor - :param torch.Tensor edge_index: A tensor of shape ``(2, E)`` - representing the indices of the graph's edges. - :param pos: A tensor of shape ``(N, D)`` representing the positions of - ``N`` points in ``D``-dimensional space. - :type pos: torch.Tensor | LabelTensor - :param edge_attr: Optional tensor of edge_featured ``(E, F')`` where - ``F'`` is the number of edge features - :type edge_attr: torch.Tensor | LabelTensor - :param bool undirected: Whether to make the graph undirected - :param dict kwargs: Additional keyword arguments passed to the - :class:`~torch_geometric.data.Data` class constructor. - """ - # preprocessing - self._preprocess_edge_index(edge_index, undirected) - - # calling init - super().__init__( - x=x, edge_index=edge_index, edge_attr=edge_attr, pos=pos, **kwargs - ) - - def _check_type_consistency(self, **kwargs): - """ - Check the consistency of the types of the input data. - - :param dict kwargs: Attributes to be checked for consistency. - """ - # default types, specified in cls.__new__, by default they are Nont - # if specified in **kwargs they get override - x, pos, edge_index, edge_attr = None, None, None, None - if "pos" in kwargs: - pos = kwargs["pos"] - self._check_pos_consistency(pos) - if "edge_index" in kwargs: - edge_index = kwargs["edge_index"] - self._check_edge_index_consistency(edge_index) - if "x" in kwargs: - x = kwargs["x"] - self._check_x_consistency(x, pos) - if "edge_attr" in kwargs: - edge_attr = kwargs["edge_attr"] - self._check_edge_attr_consistency(edge_attr, edge_index) - if "undirected" in kwargs: - undirected = kwargs["undirected"] - check_consistency(undirected, bool) - - @staticmethod - def _check_pos_consistency(pos): - """ - Check if the position tensor is consistent. - :param torch.Tensor pos: The position tensor. - :raises ValueError: If the position tensor is not consistent. - """ - if pos is not None: - check_consistency(pos, (torch.Tensor, LabelTensor)) - if pos.ndim != 2: - raise ValueError("pos must be a 2D tensor.") - - @staticmethod - def _check_edge_index_consistency(edge_index): - """ - Check if the edge index is consistent. - - :param torch.Tensor edge_index: The edge index tensor. - :raises ValueError: If the edge index tensor is not consistent. - """ - check_consistency(edge_index, (torch.Tensor, LabelTensor)) - if edge_index.ndim != 2: - raise ValueError("edge_index must be a 2D tensor.") - if edge_index.size(0) != 2: - raise ValueError("edge_index must have shape [2, num_edges].") - - @staticmethod - def _check_edge_attr_consistency(edge_attr, edge_index): - """ - Check if the edge attribute tensor is consistent in type and shape - with the edge index. - - :param edge_attr: The edge attribute tensor. - :type edge_attr: torch.Tensor | LabelTensor - :param torch.Tensor edge_index: The edge index tensor. - :raises ValueError: If the edge attribute tensor is not consistent. - """ - if edge_attr is not None: - check_consistency(edge_attr, (torch.Tensor, LabelTensor)) - if edge_attr.ndim != 2: - raise ValueError("edge_attr must be a 2D tensor.") - if edge_attr.size(0) != edge_index.size(1): - raise ValueError( - "edge_attr must have shape " - "[num_edges, num_edge_features], expected " - f"num_edges {edge_index.size(1)} " - f"got {edge_attr.size(0)}." - ) - - @staticmethod - def _check_x_consistency(x, pos=None): - """ - Check if the input tensor x is consistent with the position tensor - `pos`. - - :param x: The input tensor. - :type x: torch.Tensor | LabelTensor - :param pos: The position tensor. - :type pos: torch.Tensor | LabelTensor - :raises ValueError: If the input tensor is not consistent. - """ - if x is not None: - check_consistency(x, (torch.Tensor, LabelTensor)) - if x.ndim != 2: - raise ValueError("x must be a 2D tensor.") - if pos is not None: - if x.size(0) != pos.size(0): - raise ValueError("Inconsistent number of nodes.") - - @staticmethod - def _preprocess_edge_index(edge_index, undirected): - """ - Preprocess the edge index to make the graph undirected (if required). - - :param torch.Tensor edge_index: The edge index. - :param bool undirected: Whether the graph is undirected. - :return: The preprocessed edge index. - :rtype: torch.Tensor - """ - if undirected: - edge_index = to_undirected(edge_index) - return edge_index - - def extract(self, labels, attr="x"): - """ - Perform extraction of labels from the attribute specified by `attr`. - - :param labels: Labels to extract - :type labels: list[str] | tuple[str] | str | dict - :return: Batch object with extraction performed on x - :rtype: PinaBatch - """ - # Extract labels from LabelTensor object - tensor = getattr(self, attr).extract(labels) - # Set the extracted tensor as the new attribute - setattr(self, attr, tensor) - return self - - -class GraphBuilder: - """ - A class that allows an easy definition of :class:`Graph` instances. - """ - - def __new__( - cls, - pos, - edge_index, - x=None, - edge_attr=False, - custom_edge_func=None, - loop=True, - **kwargs, - ): - """ - Compute the edge attributes and create a new instance of the - :class:`~pina.graph.Graph` class. - - :param pos: A tensor of shape ``(N, D)`` representing the positions of - ``N`` points in ``D``-dimensional space. - :type pos: torch.Tensor or LabelTensor - :param edge_index: A tensor of shape ``(2, E)`` representing the indices - of the graph's edges. - :type edge_index: torch.Tensor - :param x: Optional tensor of node features of shape ``(N, F)``, where - ``F`` is the number of features per node. - :type x: torch.Tensor | LabelTensor, optional - :param bool edge_attr: Whether to compute the edge attributes. - :param custom_edge_func: A custom function to compute edge attributes. - If provided, overrides ``edge_attr``. - :type custom_edge_func: Callable, optional - :param bool loop: Whether to include self-loops. - :param kwargs: Additional keyword arguments passed to the - :class:`~pina.graph.Graph` class constructor. - :return: A :class:`~pina.graph.Graph` instance constructed using the - provided information. - :rtype: Graph - """ - if not loop: - edge_index = remove_self_loops(edge_index)[0] - edge_attr = cls._create_edge_attr( - pos, edge_index, edge_attr, custom_edge_func or cls._build_edge_attr - ) - return Graph( - x=x, - edge_index=edge_index, - edge_attr=edge_attr, - pos=pos, - **kwargs, - ) - - @staticmethod - def _create_edge_attr(pos, edge_index, edge_attr, func): - """ - Create the edge attributes based on the input parameters. - - :param pos: Positions of the points. - :type pos: torch.Tensor | LabelTensor - :param torch.Tensor edge_index: Edge indices. - :param bool edge_attr: Whether to compute the edge attributes. - :param Callable func: Function to compute the edge attributes. - :raises ValueError: If ``func`` is not a function. - :return: The edge attributes. - :rtype: torch.Tensor | LabelTensor | None - """ - check_consistency(edge_attr, bool) - if edge_attr: - if is_function(func): - return func(pos, edge_index) - raise ValueError("custom_edge_func must be a function.") - return None - - @staticmethod - def _build_edge_attr(pos, edge_index): - """ - Default function to compute the edge attributes. - - :param pos: Positions of the points. - :type pos: torch.Tensor | LabelTensor - :param torch.Tensor edge_index: Edge indices. - :return: The edge attributes. - :rtype: torch.Tensor - """ - return ( - (pos[edge_index[0]] - pos[edge_index[1]]) - .abs() - .as_subclass(torch.Tensor) - ) - - -class RadiusGraph(GraphBuilder): - """ - Extends the :class:`~pina.graph.GraphBuilder` class to compute - ``edge_index`` based on a radius. Each point is connected to all the points - within the radius. - """ - - def __new__(cls, pos, radius, **kwargs): - """ - Instantiate the :class:`~pina.graph.Graph` class by computing the - ``edge_index`` based on the radius provided. - - :param pos: A tensor of shape ``(N, D)`` representing the positions of - ``N`` points in ``D``-dimensional space. - :type pos: torch.Tensor | LabelTensor - :param float radius: The radius within which points are connected. - :param dict kwargs: The additional keyword arguments to be passed to - :class:`GraphBuilder` and :class:`Graph` classes. - :return: A :class:`~pina.graph.Graph` instance with the computed - ``edge_index``. - :rtype: Graph - """ - edge_index = cls.compute_radius_graph(pos, radius) - return super().__new__(cls, pos=pos, edge_index=edge_index, **kwargs) - - @staticmethod - def compute_radius_graph(points, radius): - """ - Computes the ``edge_index`` based on the radius. Each point is connected - to all the points within the radius. - - :param points: A tensor of shape ``(N, D)`` representing the positions - of ``N`` points in ``D``-dimensional space. - :type points: torch.Tensor | LabelTensor - :param float radius: The radius within which points are connected. - :return: A tensor of shape ``(2, E)``, with ``E`` number of edges, - representing the edge indices of the graph. - :rtype: torch.Tensor - """ - dist = torch.cdist(points, points, p=2) - return ( - torch.nonzero(dist <= radius, as_tuple=False) - .t() - .as_subclass(torch.Tensor) - ) - - -class KNNGraph(GraphBuilder): - """ - Extends the :class:`~pina.graph.GraphBuilder` class to compute - ``edge_index`` based on a K-nearest neighbors algorithm. - """ - - def __new__(cls, pos, neighbours, **kwargs): - """ - Instantiate the :class:`~pina.graph.Graph` class by computing the - ``edge_index`` based on the K-nearest neighbors algorithm. - - :param pos: A tensor of shape ``(N, D)`` representing the positions of - ``N`` points in ``D``-dimensional space. - :type pos: torch.Tensor | LabelTensor - :param int neighbours: The number of nearest neighbors to consider when - building the graph. - :param dict kwargs: The additional keyword arguments to be passed to - :class:`GraphBuilder` and :class:`Graph` classes. - - :return: A :class:`~pina.graph.Graph` instance with the computed - ``edge_index``. - :rtype: Graph - """ - - edge_index = cls.compute_knn_graph(pos, neighbours) - return super().__new__(cls, pos=pos, edge_index=edge_index, **kwargs) - - @staticmethod - def compute_knn_graph(points, neighbours): - """ - Computes the ``edge_index`` based on the K-nearest neighbors algorithm. - - :param points: A tensor of shape ``(N, D)`` representing the positions - of ``N`` points in ``D``-dimensional space. - :type points: torch.Tensor | LabelTensor - :param int neighbours: The number of nearest neighbors to consider when - building the graph. - :return: A tensor of shape ``(2, E)``, with ``E`` number of edges, - representing the edge indices of the graph. - :rtype: torch.Tensor - """ - dist = torch.cdist(points, points, p=2) - knn_indices = torch.topk(dist, k=neighbours, largest=False).indices - row = torch.arange(points.size(0)).repeat_interleave(neighbours) - col = knn_indices.flatten() - return torch.stack([row, col], dim=0).as_subclass(torch.Tensor) - - -class LabelBatch(Batch): - """ - Extends the :class:`~torch_geometric.data.Batch` class to include - :class:`~pina.label_tensor.LabelTensor` objects. - """ - - @classmethod - def from_data_list(cls, data_list): - """ - Create a Batch object from a list of :class:`~torch_geometric.data.Data` - or :class:`~pina.graph.Graph` objects. - - :param data_list: List of :class:`~torch_geometric.data.Data` or - :class:`~pina.graph.Graph` objects. - :type data_list: list[Data] | list[Graph] - :return: A :class:`~torch_geometric.data.Batch` object containing - the input data. - :rtype: :class:`~torch_geometric.data.Batch` - """ - # Store the labels of Data/Graph objects (all data have the same labels) - # If the data do not contain labels, labels is an empty dictionary, - # therefore the labels are not stored - labels = { - k: v.labels - for k, v in data_list[0].items() - if isinstance(v, LabelTensor) - } - - # Create a Batch object from the list of Data objects - batch = super().from_data_list(data_list) - - # Put the labels back in the Batch object - for k, v in labels.items(): - batch[k].labels = v - return batch +__all__ = [ + "Graph", + "RadiusGraph", + "KNNGraph", +] diff --git a/pina/label_tensor.py b/pina/label_tensor.py index 535954d23..78b4fafde 100644 --- a/pina/label_tensor.py +++ b/pina/label_tensor.py @@ -1,753 +1,5 @@ -"""Module for LabelTensor""" +"""Public API for LabeledTensor.""" -from copy import copy, deepcopy -import torch -from torch import Tensor +from pina._src.core.label_tensor import LabelTensor - -class LabelTensor(torch.Tensor): - """ - Extension of the :class:`torch.Tensor` class that includes labels for - each dimension. - """ - - @staticmethod - def __new__(cls, x, labels, *args, **kwargs): - """ - Create a new instance of the :class:`~pina.label_tensor.LabelTensor` - class. - - :param torch.Tensor x: :class:`torch.tensor` instance to be casted as a - :class:`~pina.label_tensor.LabelTensor`. - :param labels: Labels to assign to the tensor. - :type labels: str | list[str] | dict - :return: The instance of the :class:`~pina.label_tensor.LabelTensor` - class. - :rtype: LabelTensor - """ - - if isinstance(x, LabelTensor): - return x - return super().__new__(cls, x, *args, **kwargs) - - @property - def tensor(self): - """ - Returns the tensor part of the :class:`~pina.label_tensor.LabelTensor` - object. - - :return: Tensor part of the :class:`~pina.label_tensor.LabelTensor`. - :rtype: torch.Tensor - """ - - return self.as_subclass(Tensor) - - def __init__(self, x, labels): - """ - Initialize the :class:`~pina.label_tensor.LabelTensor` instance, by - checking the consistency of the labels and the tensor. Specifically, the - labels must match the following conditions: - - - At each dimension, the number of labels must match the size of the \ - dimension. - - At each dimension, the labels must be unique. - - The labels can be passed in the following formats: - - :Example: - >>> from pina import LabelTensor - >>> tensor = LabelTensor( - >>> torch.rand((2000, 3)), - ... {1: {"name": "space", "dof": ['a', 'b', 'c']}}) - >>> tensor = LabelTensor( - >>> torch.rand((2000, 3)), - ... ["a", "b", "c"]) - - The keys of the dictionary are the dimension indices, and the values are - dictionaries containing the labels and the name of the dimension. If - the labels are passed as a list, these are assigned to the last - dimension. - - :param torch.Tensor x: The tensor to be casted as a - :class:`~pina.label_tensor.LabelTensor`. - :param labels: Labels to assign to the tensor. - :type labels: str | list[str] | dict - :raises ValueError: If the labels are not consistent with the tensor. - """ - super().__init__() - if labels is not None: - self.labels = labels - else: - self._labels = {} - - @property - def full_labels(self): - """ - Returns the full labels of the tensor, even for the dimensions that are - not labeled. - - :return: The full labels of the tensor - :rtype: dict - """ - to_return_dict = {} - shape_tensor = self.shape - for i, value in enumerate(shape_tensor): - if i in self._labels: - to_return_dict[i] = self._labels[i] - else: - to_return_dict[i] = {"dof": range(value), "name": i} - return to_return_dict - - @property - def stored_labels(self): - """ - Returns the labels stored inside the instance. - - :return: The labels stored inside the instance. - :rtype: dict - """ - return self._labels - - @property - def labels(self): - """ - Returns the labels of the last dimension of the instance. - - :return: labels of last dimension - :rtype: list - """ - if self.ndim - 1 in self._labels: - return self._labels[self.ndim - 1]["dof"] - return None - - @labels.setter - def labels(self, labels): - """ - Set labels stored insider the instance by checking the type of the - input labels and handling it accordingly. The following types are - accepted: - - - **list**: The list of labels is assigned to the last dimension. - - **dict**: The dictionary of labels is assigned to the tensor. - - **str**: The string is assigned to the last dimension. - - :param labels: Labels to assign to the class variable _labels. - :type labels: str | list[str] | dict - """ - - if not hasattr(self, "_labels"): - self._labels = {} - if isinstance(labels, dict): - self._init_labels_from_dict(labels) - elif isinstance(labels, (list, range)): - self._init_labels_from_list(labels) - elif isinstance(labels, str): - labels = [labels] - self._init_labels_from_list(labels) - else: - raise ValueError("labels must be list, dict or string.") - - def _init_labels_from_dict(self, labels): - """ - Store the internal label representation according to the values - passed as input. - - :param dict labels: The label(s) to update. - :raises ValueError: If the dof list contains duplicates or the number of - dof does not match the tensor shape. - """ - - tensor_shape = self.shape - - def validate_dof(dof_list, dim_size): - """Validate the 'dof' list for uniqueness and size.""" - if len(dof_list) != len(set(dof_list)): - raise ValueError("dof must be unique") - if len(dof_list) != dim_size: - raise ValueError( - f"Number of dof ({len(dof_list)}) does not match " - f"tensor shape ({dim_size})" - ) - - for dim, label in labels.items(): - if isinstance(label, dict): - if "name" not in label: - label["name"] = dim - if "dof" not in label: - label["dof"] = range(tensor_shape[dim]) - if "dof" in label and "name" in label: - dof = label["dof"] - dof_list = dof if isinstance(dof, (list, range)) else [dof] - if not isinstance(dof_list, (list, range)): - raise ValueError( - f"'dof' should be a list or range, not" - f" {type(dof_list)}" - ) - validate_dof(dof_list, tensor_shape[dim]) - else: - raise ValueError( - "Labels dictionary must contain either " - " both 'name' and 'dof' keys" - ) - else: - raise ValueError( - f"Invalid label format for {dim}: Expected " - f"list or dictionary, got {type(label)}" - ) - - # Assign validated label data to internal labels - self._labels[dim] = label - - def _init_labels_from_list(self, labels): - """ - Given a list of dof, this method update the internal label - representation by assigning the dof to the last dimension. - - :param labels: The label(s) to update. - :type labels: list - """ - - # Create a dict with labels - last_dim_labels = { - self.ndim - 1: {"dof": labels, "name": self.ndim - 1} - } - self._init_labels_from_dict(last_dim_labels) - - def extract(self, labels_to_extract): - """ - Extract the subset of the original tensor by returning all the positions - corresponding to the passed ``label_to_extract``. If - ``label_to_extract`` is a dictionary, the keys are the dimension names - and the values are the labels to extract. If a single label or a list - of labels is passed, the last dimension is considered. - - :Example: - >>> from pina import LabelTensor - >>> labels = {1: {'dof': ["a", "b", "c"], 'name': 'space'}} - >>> tensor = LabelTensor(torch.rand((2000, 3)), labels) - >>> tensor.extract("a") - >>> tensor.extract(["a", "b"]) - >>> tensor.extract({"space": ["a", "b"]}) - - :param labels_to_extract: The label(s) to extract. - :type labels_to_extract: str | list[str] | tuple[str] | dict - :return: The extracted tensor with the updated labels. - :rtype: LabelTensor - - :raises TypeError: Labels are not ``str``, ``list[str]`` or ``dict`` - properly setted. - :raises ValueError: Label to extract is not in the labels ``list``. - """ - - def get_label_indices(dim_labels, labels_te): - if isinstance(labels_te, (int, str)): - labels_te = [labels_te] - return ( - [dim_labels.index(label) for label in labels_te] - if len(labels_te) > 1 - else slice( - dim_labels.index(labels_te[0]), - dim_labels.index(labels_te[0]) + 1, - ) - ) - - # Ensure labels_to_extract is a list or dict - if isinstance(labels_to_extract, (str, int)): - labels_to_extract = [labels_to_extract] - - labels = copy(self._labels) - - # Get the dimension names and the respective dimension index - dim_names = {labels[dim]["name"]: dim for dim in labels} - ndim = super().ndim - tensor = self.tensor.as_subclass(torch.Tensor) - - # Convert list/tuple to a dict for the last dimension if applicable - if isinstance(labels_to_extract, (list, tuple)): - last_dim = ndim - 1 - dim_name = labels[last_dim]["name"] - labels_to_extract = {dim_name: list(labels_to_extract)} - - # Validate the labels_to_extract type - if not isinstance(labels_to_extract, dict): - raise ValueError( - "labels_to_extract must be a string, list, or dictionary." - ) - - # Perform the extraction for each specified dimension - for dim_name, labels_te in labels_to_extract.items(): - if dim_name not in dim_names: - raise ValueError( - f"Cannot extract labels for dimension '{dim_name}' as it is" - f" not present in the original labels." - ) - - idx_dim = dim_names[dim_name] - dim_labels = labels[idx_dim]["dof"] - indices = get_label_indices(dim_labels, labels_te) - - extractor = [slice(None)] * ndim - extractor[idx_dim] = indices - tensor = tensor[tuple(extractor)] - - labels[idx_dim] = {"dof": labels_te, "name": dim_name} - - return LabelTensor(tensor, labels) - - def __str__(self): - """ - The string representation of the - :class:`~pina.label_tensor.LabelTensor`. - - :return: String representation of the - :class:`~pina.label_tensor.LabelTensor` instance. - :rtype: str - """ - - s = "" - for key, value in self._labels.items(): - s += f"{key}: {value}\n" - s += "\n" - s += self.tensor.__str__() - return s - - @staticmethod - def cat(tensors, dim=0): - """ - Concatenate a list of tensors along a specified dimension. For more - details, see :meth:`torch.cat`. - - :param list[LabelTensor] tensors: - :class:`~pina.label_tensor.LabelTensor` instances to concatenate - :param int dim: Dimensions on which you want to perform the operation - (default is 0) - :return: A new :class:`LabelTensor` instance obtained by concatenating - the input instances. - - :rtype: LabelTensor - :raises ValueError: either number dof or dimensions names differ. - """ - - if not tensors: - return [] # Handle empty list - if len(tensors) == 1: - return tensors[0] # Return single tensor as-is - - # Perform concatenation - cat_tensor = torch.cat(tensors, dim=dim) - tensors_labels = [tensor.stored_labels for tensor in tensors] - - # Check label consistency across tensors, excluding the - # concatenation dimension - for key in tensors_labels[0]: - if key != dim: - if any( - tensors_labels[i][key] != tensors_labels[0][key] - for i in range(len(tensors_labels)) - ): - raise RuntimeError( - f"Tensors must have the same labels along all " - f"dimensions except {dim}." - ) - - # Copy and update the 'dof' for the concatenation dimension - cat_labels = {k: copy(v) for k, v in tensors_labels[0].items()} - - # Update labels if the concatenation dimension has labels - if dim in tensors[0].stored_labels: - if dim in cat_labels: - cat_dofs = [label[dim]["dof"] for label in tensors_labels] - cat_labels[dim]["dof"] = sum(cat_dofs, []) - else: - cat_labels = tensors[0].stored_labels - - # Assign updated labels to the concatenated tensor - cat_tensor._labels = cat_labels - return cat_tensor - - @staticmethod - def stack(tensors): - """ - Stacks a list of tensors along a new dimension. For more details, see - :meth:`torch.stack`. - - :param list[LabelTensor] tensors: A list of tensors to stack. - All tensors must have the same shape. - :return: A new :class:`~pina.label_tensor.LabelTensor` instance obtained - by stacking the input tensors. - :rtype: LabelTensor - """ - - # Perform stacking in torch - new_tensor = torch.stack(tensors) - - # Increase labels keys by 1 - labels = tensors[0]._labels - labels = {key + 1: value for key, value in labels.items()} - new_tensor._labels = labels - return new_tensor - - def requires_grad_(self, mode=True): - """ - Override the :meth:`~torch.Tensor.requires_grad_` method to handle - the labels in the new tensor. - For more details, see :meth:`~torch.Tensor.requires_grad_`. - - :param bool mode: A boolean value indicating whether the tensor should - track gradients.If `True`, the tensor will track gradients; - if `False`, it will not. - :return: The :class:`~pina.label_tensor.LabelTensor` itself with the - updated ``requires_grad`` state and retained labels. - :rtype: LabelTensor - """ - - lt = super().requires_grad_(mode) - lt._labels = self._labels - return lt - - @property - def dtype(self): - """ - Give the ``dtype`` of the tensor. For more details, see - :meth:`torch.dtype`. - - :return: The data type of the tensor. - :rtype: torch.dtype - """ - - return super().dtype - - def to(self, *args, **kwargs): - """ - Performs Tensor dtype and/or device conversion. For more details, see - :meth:`torch.Tensor.to`. - - :return: A new :class:`~pina.label_tensor.LabelTensor` instance with the - updated dtype and/or device and retained labels. - :rtype: LabelTensor - """ - - lt = super().to(*args, **kwargs) - lt._labels = self._labels - return lt - - def clone(self, *args, **kwargs): - """ - Clone the :class:`~pina.label_tensor.LabelTensor`. For more details, see - :meth:`torch.Tensor.clone`. - - :return: A new :class:`~pina.label_tensor.LabelTensor` instance with the - same data and labels but allocated in a different memory location. - :rtype: LabelTensor - """ - - out = LabelTensor( - super().clone(*args, **kwargs), deepcopy(self._labels) - ) - return out - - def append(self, tensor, mode="std"): - """ - Appends a given tensor to the current tensor along the last dimension. - This method supports two types of appending operations: - - 1. **Standard append** ("std"): Concatenates the input tensor with the \ - current tensor along the last dimension. - 2. **Cross append** ("cross"): Creates a cross-product of the current \ - tensor and the input tensor. - - :param tensor: The tensor to append to the current tensor. - :type tensor: LabelTensor - :param mode: The append mode to use. Defaults to ``st``. - :type mode: str, optional - :return: A new :class:`LabelTensor` instance obtained by appending the - input tensor. - :rtype: LabelTensor - - :raises ValueError: If the mode is not "std" or "cross". - """ - - if mode == "std": - # Call cat on last dimension - new_label_tensor = LabelTensor.cat( - [self, tensor], dim=self.ndim - 1 - ) - return new_label_tensor - if mode == "cross": - # Crete tensor and call cat on last dimension - tensor1 = self - tensor2 = tensor - n1 = tensor1.shape[0] - n2 = tensor2.shape[0] - tensor1 = LabelTensor(tensor1.repeat(n2, 1), labels=tensor1.labels) - tensor2 = LabelTensor( - tensor2.repeat_interleave(n1, dim=0), labels=tensor2.labels - ) - new_label_tensor = LabelTensor.cat( - [tensor1, tensor2], dim=self.ndim - 1 - ) - return new_label_tensor - raise ValueError('mode must be either "std" or "cross"') - - @staticmethod - def vstack(tensors): - """ - Stack tensors vertically. For more details, see :meth:`torch.vstack`. - - :param list of LabelTensor label_tensors: The - :class:`~pina.label_tensor.LabelTensor` instances to stack. They - need to have equal labels. - :return: A new :class:`~pina.label_tensor.LabelTensor` instance obtained - by stacking the input tensors vertically. - :rtype: LabelTensor - """ - - return LabelTensor.cat(tensors, dim=0) - - # This method is used to update labels - def _update_single_label(self, index, dim): - """ - Update the labels of the tensor based on the index (or list of indices). - - :param index: Index of dof to retain. - :type index: int | slice | list[int] | tuple[int] | torch.Tensor - :param int dim: Dimension of the indexes in the original tensor. - :return: The updated labels for the specified dimension. - :rtype: list[int] - :raises: ValueError: If the index type is not supported. - """ - old_dof = self._labels[dim]["dof"] - # Handle slicing - if isinstance(index, slice): - new_dof = old_dof[index] - # Handle single integer index - elif isinstance(index, int): - new_dof = [old_dof[index]] - # Handle lists or tensors - elif isinstance(index, (list, torch.Tensor)): - # Handle list of bools - if isinstance(index, torch.Tensor) and index.dtype == torch.bool: - index = index.nonzero().squeeze() - new_dof = ( - [old_dof[i] for i in index] - if isinstance(old_dof, list) - else index - ) - else: - raise NotImplementedError( - f"Unsupported index type: {type(index)}. Expected slice, int, " - f"list, or torch.Tensor." - ) - return new_dof - - def __getitem__(self, index): - """ " - Override the __getitem__ method to handle the labels of the - :class:`~pina.label_tensor.LabelTensor` instance. It first performs - __getitem__ operation on the :class:`torch.Tensor` part of the instance, - then updates the labels based on the index. - - :param index: The index used to access the item - :type index: int | str | tuple of int | list ot int | torch.Tensor - :return: A new :class:`~pina.label_tensor.LabelTensor` instance obtained - `__getitem__` operation on :class:`torch.Tensor` part of the - instance, with the updated labels. - :rtype: LabelTensor - - :raises KeyError: If an invalid label index is provided. - :raises IndexError: If an invalid index is accessed in the tensor. - """ - - # Handle string index - if isinstance(index, str) or ( - isinstance(index, (tuple, list)) - and all(isinstance(i, str) for i in index) - ): - return self.extract(index) - - # Retrieve selected tensor and labels - selected_tensor = super().__getitem__(index) - if not hasattr(self, "_labels"): - return selected_tensor - - original_labels = self._labels - updated_labels = copy(original_labels) - - # Ensure the index is iterable - if not isinstance(index, tuple): - index = [index] - - # Update labels based on the index - offset = 0 - removed = 0 - for dim, idx in enumerate(index): - if dim in original_labels: - if isinstance(idx, int): - # Compute the working dimension considering the removed - # dimensions due to int index on a non labled dimension - dim_ = dim - removed - selected_tensor = selected_tensor.unsqueeze(dim_) - if idx != slice(None): - # Update the labels for the selected dimension - updated_labels[offset] = { - "dof": self._update_single_label(idx, dim), - "name": original_labels[dim]["name"], - } - else: - # Adjust label keys if dimension is reduced (case of integer - # index on a non-labeled dimension) - if isinstance(idx, int): - updated_labels = { - key - 1 if key > dim else key: value - for key, value in updated_labels.items() - } - removed += 1 - continue - offset += 1 - - # Update the selected tensor's labels - selected_tensor._labels = updated_labels - return selected_tensor - - def sort_labels(self, dim=None): - """ - Sort the labels along the specified dimension and apply. It applies the - same sorting to the tensor part of the instance. - - :param int dim: The dimension along which to sort the labels. - If ``None``, the last dimension is used. - :return: A new tensor with sorted labels along the specified dimension. - :rtype: LabelTensor - """ - - def arg_sort(lst): - return sorted(range(len(lst)), key=lambda x: lst[x]) - - if dim is None: - dim = self.ndim - 1 - if self.shape[dim] == 1: - return self - labels = self.stored_labels[dim]["dof"] - sorted_index = arg_sort(labels) - # Define an indexer to sort the tensor along the specified dimension - indexer = [slice(None)] * self.ndim - # Assigned the sorted index to the specified dimension - indexer[dim] = sorted_index - return self[tuple(indexer)] - - def __deepcopy__(self, memo): - """ - Creates a deep copy of the object. For more details, see - :meth:`copy.deepcopy`. - - :param memo: LabelTensor object to be copied. - :type memo: LabelTensor - :return: A deep copy of the original LabelTensor object. - :rtype: LabelTensor - """ - - cls = self.__class__ - result = cls(deepcopy(self.tensor), deepcopy(self.stored_labels)) - return result - - def permute(self, *dims): - """ - Permutes the dimensions of the tensor and the associated labels - accordingly. For more details, see :meth:`torch.Tensor.permute`. - - :param dims: The dimensions to permute the tensor to. - :type dims: tuple[int] | list[int] - :return: A new object with permuted dimensions and reordered labels. - :rtype: LabelTensor - """ - # Call the base class permute method - tensor = super().permute(*dims) - - # Update lables - labels = self._labels - keys_list = list(*dims) - labels = {keys_list.index(k): v for k, v in labels.items()} - - # Assign labels to the new tensor - tensor._labels = labels - return tensor - - def detach(self): - """ - Detaches the tensor from the computation graph and retains the stored - labels. For more details, see :meth:`torch.Tensor.detach`. - - :return: A new tensor detached from the computation graph. - :rtype: LabelTensor - """ - - lt = super().detach() - - # Copy the labels to the new tensor only if present - if hasattr(self, "_labels"): - lt._labels = self.stored_labels - return lt - - @staticmethod - def summation(tensors): - """ - Computes the summation of a list of - :class:`~pina.label_tensor.LabelTensor` instances. - - - :param list[LabelTensor] tensors: A list of tensors to sum. All - tensors must have the same shape and labels. - :return: A new `LabelTensor` containing the element-wise sum of the - input tensors. - :rtype: LabelTensor - - :raises ValueError: If the input `tensors` list is empty. - :raises RuntimeError: If the tensors have different shapes and/or - mismatched labels. - """ - - if not tensors: - raise ValueError("The tensors list must not be empty.") - - if len(tensors) == 1: - return tensors[0] - - # Initialize result tensor and labels - data = torch.zeros_like(tensors[0].tensor).to(tensors[0].device) - last_dim_labels = [] - - # Accumulate tensors - for tensor in tensors: - data += tensor.tensor - last_dim_labels.append(tensor.labels) - - # Construct last dimension labels - last_dim_labels = ["+".join(items) for items in zip(*last_dim_labels)] - - # Update the labels for the resulting tensor - labels = {k: copy(v) for k, v in tensors[0].stored_labels.items()} - labels[tensors[0].ndim - 1] = { - "dof": last_dim_labels, - "name": tensors[0].name, - } - - return LabelTensor(data, labels) - - def reshape(self, *shape): - """ - Override the reshape method to update the labels of the tensor. - For more details, see :meth:`torch.Tensor.reshape`. - - :param tuple of int shape: The new shape of the tensor. - :return: A new :class:`~pina.label_tensor.LabelTensor` instance with the - updated shape and labels. - :rtype: LabelTensor - """ - - # As for now the reshape method is used only in the context of the - # dataset, the labels are not - tensor = super().reshape(*shape) - if not hasattr(self, "_labels") or shape != (-1, *self.shape[2:]): - return tensor - tensor.labels = self.labels - return tensor +__all__ = ["LabelTensor"] diff --git a/pina/loss/__init__.py b/pina/loss/__init__.py index d91cf7ab0..83ad5ef7e 100644 --- a/pina/loss/__init__.py +++ b/pina/loss/__init__.py @@ -1,4 +1,10 @@ -"""Module for loss functions and weighting functions.""" +"""Loss functions and balancing strategies for multi-objective optimization. + +This module provides standard error metrics (Lp, Power loss) and sophisticated +weighting schemes designed to balance residual, boundary, and data-driven loss +terms, including dynamic methods like Neural Tangent Kernel (NTK) and +self-adaptive weighting. +""" __all__ = [ "LossInterface", @@ -11,11 +17,11 @@ "LinearWeighting", ] -from .loss_interface import LossInterface -from .power_loss import PowerLoss -from .lp_loss import LpLoss -from .weighting_interface import WeightingInterface -from .scalar_weighting import ScalarWeighting -from .ntk_weighting import NeuralTangentKernelWeighting -from .self_adaptive_weighting import SelfAdaptiveWeighting -from .linear_weighting import LinearWeighting +from pina._src.loss.loss_interface import LossInterface +from pina._src.loss.power_loss import PowerLoss +from pina._src.loss.lp_loss import LpLoss +from pina._src.loss.weighting_interface import WeightingInterface +from pina._src.loss.scalar_weighting import ScalarWeighting +from pina._src.loss.ntk_weighting import NeuralTangentKernelWeighting +from pina._src.loss.self_adaptive_weighting import SelfAdaptiveWeighting +from pina._src.loss.linear_weighting import LinearWeighting diff --git a/pina/model/__init__.py b/pina/model/__init__.py index 05ccc6c8c..0310eef5c 100644 --- a/pina/model/__init__.py +++ b/pina/model/__init__.py @@ -16,18 +16,21 @@ "PirateNet", "EquivariantGraphNeuralOperator", "SINDy", + "SplineSurface", ] -from .feed_forward import FeedForward, ResidualFeedForward -from .multi_feed_forward import MultiFeedForward -from .deeponet import DeepONet, MIONet -from .fourier_neural_operator import FNO, FourierIntegralKernel -from .kernel_neural_operator import KernelNeuralOperator -from .average_neural_operator import AveragingNeuralOperator -from .low_rank_neural_operator import LowRankNeuralOperator -from .spline import Spline -from .spline_surface import SplineSurface -from .graph_neural_operator import GraphNeuralOperator -from .pirate_network import PirateNet -from .equivariant_graph_neural_operator import EquivariantGraphNeuralOperator -from .sindy import SINDy +from pina._src.model.feed_forward import FeedForward, ResidualFeedForward +from pina._src.model.multi_feed_forward import MultiFeedForward +from pina._src.model.deeponet import DeepONet, MIONet +from pina._src.model.fourier_neural_operator import FNO, FourierIntegralKernel +from pina._src.model.kernel_neural_operator import KernelNeuralOperator +from pina._src.model.average_neural_operator import AveragingNeuralOperator +from pina._src.model.low_rank_neural_operator import LowRankNeuralOperator +from pina._src.model.spline import Spline +from pina._src.model.spline_surface import SplineSurface +from pina._src.model.graph_neural_operator import GraphNeuralOperator +from pina._src.model.pirate_network import PirateNet +from pina._src.model.equivariant_graph_neural_operator import ( + EquivariantGraphNeuralOperator, +) +from pina._src.model.sindy import SINDy diff --git a/pina/model/block/__init__.py b/pina/model/block/__init__.py index 08b313387..88bfd9e43 100644 --- a/pina/model/block/__init__.py +++ b/pina/model/block/__init__.py @@ -1,4 +1,10 @@ -"""Module for the building blocks of the neural models.""" +"""Architectural primitives and building blocks. + +This module provides a comprehensive collection of neural network components, +ranging from standard units (Residual, Enhanced Linear) to specialized layers +for Scientific Machine Learning, including Neural Operator blocks (FNO, GNO, +AVNO), spectral convolutions, and coordinate embeddings (Fourier Features). +""" __all__ = [ "ContinuousConvBlock", @@ -21,19 +27,26 @@ "PirateNetBlock", ] -from .convolution_2d import ContinuousConvBlock -from .residual import ResidualBlock, EnhancedLinear -from .spectral import ( +from pina._src.model.block.convolution_2d import ContinuousConvBlock +from pina._src.model.block.residual import ResidualBlock, EnhancedLinear +from pina._src.model.block.spectral import ( SpectralConvBlock1D, SpectralConvBlock2D, SpectralConvBlock3D, ) -from .fourier_block import FourierBlock1D, FourierBlock2D, FourierBlock3D -from .pod_block import PODBlock -from .orthogonal import OrthogonalBlock -from .embedding import PeriodicBoundaryEmbedding, FourierFeatureEmbedding -from .average_neural_operator_block import AVNOBlock -from .low_rank_block import LowRankBlock -from .rbf_block import RBFBlock -from .gno_block import GNOBlock -from .pirate_network_block import PirateNetBlock +from pina._src.model.block.fourier_block import ( + FourierBlock1D, + FourierBlock2D, + FourierBlock3D, +) +from pina._src.model.block.pod_block import PODBlock +from pina._src.model.block.orthogonal import OrthogonalBlock +from pina._src.model.block.embedding import ( + PeriodicBoundaryEmbedding, + FourierFeatureEmbedding, +) +from pina._src.model.block.average_neural_operator_block import AVNOBlock +from pina._src.model.block.low_rank_block import LowRankBlock +from pina._src.model.block.rbf_block import RBFBlock +from pina._src.model.block.gno_block import GNOBlock +from pina._src.model.block.pirate_network_block import PirateNetBlock diff --git a/pina/model/block/message_passing.py b/pina/model/block/message_passing.py new file mode 100644 index 000000000..652e9dbde --- /dev/null +++ b/pina/model/block/message_passing.py @@ -0,0 +1,25 @@ +"""Module for the message passing blocks of the graph neural models.""" + +__all__ = [ + "InteractionNetworkBlock", + "DeepTensorNetworkBlock", + "EnEquivariantNetworkBlock", + "RadialFieldNetworkBlock", + "EquivariantGraphNeuralOperatorBlock", +] + +from pina._src.model.block.message_passing.interaction_network_block import ( + InteractionNetworkBlock, +) +from pina._src.model.block.message_passing.deep_tensor_network_block import ( + DeepTensorNetworkBlock, +) +from pina._src.model.block.message_passing.en_equivariant_network_block import ( + EnEquivariantNetworkBlock, +) +from pina._src.model.block.message_passing.radial_field_network_block import ( + RadialFieldNetworkBlock, +) +from pina._src.model.block.message_passing.equivariant_graph_neural_operator_block import ( + EquivariantGraphNeuralOperatorBlock, +) diff --git a/pina/model/block/message_passing/__init__.py b/pina/model/block/message_passing/__init__.py deleted file mode 100644 index 202e1fde4..000000000 --- a/pina/model/block/message_passing/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -"""Module for the message passing blocks of the graph neural models.""" - -__all__ = [ - "InteractionNetworkBlock", - "DeepTensorNetworkBlock", - "EnEquivariantNetworkBlock", - "RadialFieldNetworkBlock", - "EquivariantGraphNeuralOperatorBlock", -] - -from .interaction_network_block import InteractionNetworkBlock -from .deep_tensor_network_block import DeepTensorNetworkBlock -from .en_equivariant_network_block import EnEquivariantNetworkBlock -from .radial_field_network_block import RadialFieldNetworkBlock -from .equivariant_graph_neural_operator_block import ( - EquivariantGraphNeuralOperatorBlock, -) diff --git a/pina/operator.py b/pina/operator.py index bf2351bce..fcd214804 100644 --- a/pina/operator.py +++ b/pina/operator.py @@ -1,483 +1,29 @@ -""" -Module for vectorized differential operators implementation. - -Differential operators are used to define differential problems and are -implemented to run efficiently on various accelerators, including CPU, GPU, TPU, -and MPS. - -Each differential operator takes the following inputs: -- A tensor on which the operator is applied. -- A tensor with respect to which the operator is computed. -- The names of the output variables for which the operator is evaluated. -- The names of the variables with respect to which the operator is computed. +"""A public API for differential operators and automatic differentiation utilities. -Each differential operator has its fast version, which performs no internal -checks on input and output tensors. For these methods, the user is always -required to specify both ``components`` and ``d`` as lists of strings. +This module provides standard vector calculus operators (gradient, divergence, +laplacian, advection) implemented using automatic differentiation. It includes +both high-level general operators and optimized 'fast' variants for improved +computational efficiency during training. """ -import torch -from .label_tensor import LabelTensor - - -def _check_values(output_, input_, components, d): - """ - Perform checks on arguments of differential operators. - - :param LabelTensor output_: The output tensor on which the operator is - computed. - :param LabelTensor input_: The input tensor with respect to which the - operator is computed. - :param components: The names of the output variables for which to compute - the operator. It must be a subset of the output labels. - If ``None``, all output variables are considered. Default is ``None``. - :type components: str | list[str] - :param d: The names of the input variables with respect to which the - operator is computed. It must be a subset of the input labels. - If ``None``, all input variables are considered. Default is ``None``. - :type d: str | list[str] - :raises TypeError: If the input tensor is not a LabelTensor. - :raises TypeError: If the output tensor is not a LabelTensor. - :raises RuntimeError: If derivative labels are missing from the ``input_``. - :raises RuntimeError: If component labels are missing from the ``output_``. - :return: The components and d lists. - :rtype: tuple[list[str], list[str]] - """ - # Check if the input is a LabelTensor - if not isinstance(input_, LabelTensor): - raise TypeError("Input must be a LabelTensor.") - - # Check if the output is a LabelTensor - if not isinstance(output_, LabelTensor): - raise TypeError("Output must be a LabelTensor.") - - # If no labels are provided, use all labels - d = d or input_.labels - components = components or output_.labels - - # Convert to list if not already - d = d if isinstance(d, list) else [d] - components = components if isinstance(components, list) else [components] - - # Check if all labels are present in the input tensor - if not all(di in input_.labels for di in d): - raise RuntimeError("Derivative labels missing from input tensor.") - - # Check if all labels are present in the output tensor - if not all(c in output_.labels for c in components): - raise RuntimeError("Component label missing from output tensor.") - - return components, d - - -def _scalar_grad(output_, input_, d): - """ - Compute the gradient of a scalar-valued ``output_``. - - :param LabelTensor output_: The output tensor on which the gradient is - computed. It must be a column tensor. - :param LabelTensor input_: The input tensor with respect to which the - gradient is computed. - :param list[str] d: The names of the input variables with respect to - which the gradient is computed. It must be a subset of the input - labels. If ``None``, all input variables are considered. - :return: The computed gradient tensor. - :rtype: LabelTensor - """ - grad_out = torch.autograd.grad( - outputs=output_, - inputs=input_, - grad_outputs=torch.ones_like(output_), - create_graph=True, - retain_graph=True, - allow_unused=True, - )[0] - - return grad_out[..., [input_.labels.index(i) for i in d]] - - -def _scalar_laplacian(output_, input_, d): - """ - Compute the laplacian of a scalar-valued ``output_``. - - :param LabelTensor output_: The output tensor on which the laplacian is - computed. It must be a column tensor. - :param LabelTensor input_: The input tensor with respect to which the - laplacian is computed. - :param list[str] d: The names of the input variables with respect to - which the laplacian is computed. It must be a subset of the input - labels. If ``None``, all input variables are considered. - :return: The computed laplacian tensor. - :rtype: LabelTensor - """ - first_grad = fast_grad( - output_=output_, input_=input_, components=output_.labels, d=d - ) - second_grad = fast_grad( - output_=first_grad, input_=input_, components=first_grad.labels, d=d - ) - labels_to_extract = [f"d{c}d{d_}" for c, d_ in zip(first_grad.labels, d)] - return torch.sum( - second_grad.extract(labels_to_extract), dim=-1, keepdim=True - ) - - -def fast_grad(output_, input_, components, d): - """ - Compute the gradient of the ``output_`` with respect to the ``input``. - - Unlike ``grad``, this function performs no internal checks on input and - output tensors. The user is required to specify both ``components`` and - ``d`` as lists of strings. It is designed to enhance computation speed. - - This operator supports both vector-valued and scalar-valued functions with - one or multiple input coordinates. - - :param LabelTensor output_: The output tensor on which the gradient is - computed. - :param LabelTensor input_: The input tensor with respect to which the - gradient is computed. - :param list[str] components: The names of the output variables for which to - compute the gradient. It must be a subset of the output labels. - :param list[str] d: The names of the input variables with respect to which - the gradient is computed. It must be a subset of the input labels. - :return: The computed gradient tensor. - :rtype: LabelTensor - """ - # Scalar gradient - if output_.shape[-1] == 1: - return LabelTensor( - _scalar_grad(output_=output_, input_=input_, d=d), - labels=[f"d{output_.labels[0]}d{i}" for i in d], - ) - - # Vector gradient - grads = torch.cat( - [ - _scalar_grad(output_=output_.extract(c), input_=input_, d=d) - for c in components - ], - dim=-1, - ) - - return LabelTensor( - grads, labels=[f"d{c}d{i}" for c in components for i in d] - ) - - -def fast_div(output_, input_, components, d): - """ - Compute the divergence of the ``output_`` with respect to ``input``. - - Unlike ``div``, this function performs no internal checks on input and - output tensors. The user is required to specify both ``components`` and - ``d`` as lists of strings. It is designed to enhance computation speed. - - This operator supports vector-valued functions with multiple input - coordinates. - - :param LabelTensor output_: The output tensor on which the divergence is - computed. - :param LabelTensor input_: The input tensor with respect to which the - divergence is computed. - :param list[str] components: The names of the output variables for which to - compute the divergence. It must be a subset of the output labels. - :param list[str] d: The names of the input variables with respect to which - the divergence is computed. It must be a subset of the input labels. - :rtype: LabelTensor - """ - grad_out = fast_grad( - output_=output_, input_=input_, components=components, d=d - ) - tensors_to_sum = [ - grad_out.extract(f"d{c}d{d_}") for c, d_ in zip(components, d) - ] - - return LabelTensor.summation(tensors_to_sum) - - -def fast_laplacian(output_, input_, components, d, method="std"): - """ - Compute the laplacian of the ``output_`` with respect to ``input``. - - Unlike ``laplacian``, this function performs no internal checks on input and - output tensors. The user is required to specify both ``components`` and - ``d`` as lists of strings. It is designed to enhance computation speed. - - This operator supports both vector-valued and scalar-valued functions with - one or multiple input coordinates. - - :param LabelTensor output_: The output tensor on which the laplacian is - computed. - :param LabelTensor input_: The input tensor with respect to which the - laplacian is computed. - :param list[str] components: The names of the output variables for which to - compute the laplacian. It must be a subset of the output labels. - :param list[str] d: The names of the input variables with respect to which - the laplacian is computed. It must be a subset of the input labels. - :param str method: The method used to compute the Laplacian. Available - methods are ``std`` and ``divgrad``. The ``std`` method computes the - trace of the Hessian matrix, while the ``divgrad`` method computes the - divergence of the gradient. Default is ``std``. - :return: The computed laplacian tensor. - :rtype: LabelTensor - :raises ValueError: If the passed method is neither ``std`` nor ``divgrad``. - """ - # Scalar laplacian - if output_.shape[-1] == 1: - return LabelTensor( - _scalar_laplacian(output_=output_, input_=input_, d=d), - labels=[f"dd{c}" for c in components], - ) - - # Initialize the result tensor and its labels - labels = [f"dd{c}" for c in components] - result = torch.empty( - input_.shape[0], len(components), device=output_.device - ) - - # Vector laplacian - if method == "std": - result = torch.cat( - [ - _scalar_laplacian( - output_=output_.extract(c), input_=input_, d=d - ) - for c in components - ], - dim=-1, - ) - - elif method == "divgrad": - grads = fast_grad( - output_=output_, input_=input_, components=components, d=d - ) - result = torch.cat( - [ - fast_div( - output_=grads, - input_=input_, - components=[f"d{c}d{i}" for i in d], - d=d, - ) - for c in components - ], - dim=-1, - ) - - else: - raise ValueError( - "Invalid method. Available methods are ``std`` and ``divgrad``." - ) - - return LabelTensor(result, labels=labels) - - -def fast_advection(output_, input_, velocity_field, components, d): - """ - Perform the advection operation on the ``output_`` with respect to the - ``input``. This operator supports vector-valued functions with multiple - input coordinates. - - Unlike ``advection``, this function performs no internal checks on input and - output tensors. The user is required to specify both ``components`` and - ``d`` as lists of strings. It is designed to enhance computation speed. - - :param LabelTensor output_: The output tensor on which the advection is - computed. It includes both the velocity and the quantity to be advected. - :param LabelTensor input_: the input tensor with respect to which advection - is computed. - :param list[str] velocity_field: The name of the output variables used as - velocity field. It must be chosen among the output labels. - :param list[str] components: The names of the output variables for which to - compute the advection. It must be a subset of the output labels. - :param list[str] d: The names of the input variables with respect to which - the advection is computed. It must be a subset of the input labels. - :return: The computed advection tensor. - :rtype: LabelTensor - """ - # Add a dimension to the velocity field for following operations - velocity = output_.extract(velocity_field).unsqueeze(-1) - - # Compute the gradient - grads = fast_grad( - output_=output_, input_=input_, components=components, d=d - ) - - # Reshape into [..., len(filter_components), len(d)] - tmp = grads.reshape(*output_.shape[:-1], len(components), len(d)) - - # Transpose to [..., len(d), len(filter_components)] - tmp = tmp.transpose(-1, -2) - - adv = (tmp * velocity).sum(dim=tmp.tensor.ndim - 2) - return LabelTensor(adv, labels=[f"adv_{c}" for c in components]) - - -def grad(output_, input_, components=None, d=None): - """ - Compute the gradient of the ``output_`` with respect to the ``input``. - - This operator supports both vector-valued and scalar-valued functions with - one or multiple input coordinates. - - :param LabelTensor output_: The output tensor on which the gradient is - computed. - :param LabelTensor input_: The input tensor with respect to which the - gradient is computed. - :param components: The names of the output variables for which to compute - the gradient. It must be a subset of the output labels. - If ``None``, all output variables are considered. Default is ``None``. - :type components: str | list[str] - :param d: The names of the input variables with respect to which the - gradient is computed. It must be a subset of the input labels. - If ``None``, all input variables are considered. Default is ``None``. - :type d: str | list[str] - :raises TypeError: If the input tensor is not a LabelTensor. - :raises TypeError: If the output tensor is not a LabelTensor. - :raises RuntimeError: If derivative labels are missing from the ``input_``. - :raises RuntimeError: If component labels are missing from the ``output_``. - :return: The computed gradient tensor. - :rtype: LabelTensor - """ - components, d = _check_values( - output_=output_, input_=input_, components=components, d=d - ) - return fast_grad(output_=output_, input_=input_, components=components, d=d) - - -def div(output_, input_, components=None, d=None): - """ - Compute the divergence of the ``output_`` with respect to ``input``. - - This operator supports vector-valued functions with multiple input - coordinates. - - :param LabelTensor output_: The output tensor on which the divergence is - computed. - :param LabelTensor input_: The input tensor with respect to which the - divergence is computed. - :param components: The names of the output variables for which to compute - the divergence. It must be a subset of the output labels. - If ``None``, all output variables are considered. Default is ``None``. - :type components: str | list[str] - :param d: The names of the input variables with respect to which the - divergence is computed. It must be a subset of the input labels. - If ``None``, all input variables are considered. Default is ``None``. - :type components: str | list[str] - :raises TypeError: If the input tensor is not a LabelTensor. - :raises TypeError: If the output tensor is not a LabelTensor. - :raises ValueError: If the length of ``components`` and ``d`` do not match. - :return: The computed divergence tensor. - :rtype: LabelTensor - """ - components, d = _check_values( - output_=output_, input_=input_, components=components, d=d - ) - - # Components and d must be of the same length - if len(components) != len(d): - raise ValueError( - "Divergence requires components and d to be of the same length." - ) - - return fast_div(output_=output_, input_=input_, components=components, d=d) - - -def laplacian(output_, input_, components=None, d=None, method="std"): - """ - Compute the laplacian of the ``output_`` with respect to ``input``. - - This operator supports both vector-valued and scalar-valued functions with - one or multiple input coordinates. - - :param LabelTensor output_: The output tensor on which the laplacian is - computed. - :param LabelTensor input_: The input tensor with respect to which the - laplacian is computed. - :param components: The names of the output variables for which to - compute the laplacian. It must be a subset of the output labels. - If ``None``, all output variables are considered. Default is ``None``. - :type components: str | list[str] - :param d: The names of the input variables with respect to which - the laplacian is computed. It must be a subset of the input labels. - If ``None``, all input variables are considered. Default is ``None``. - :type d: str | list[str] - :param str method: The method used to compute the Laplacian. Available - methods are ``std`` and ``divgrad``. The ``std`` method computes the - trace of the Hessian matrix, while the ``divgrad`` method computes the - divergence of the gradient. Default is ``std``. - :raises TypeError: If the input tensor is not a LabelTensor. - :raises TypeError: If the output tensor is not a LabelTensor. - :raises ValueError: If the passed method is neither ``std`` nor ``divgrad``. - :return: The computed laplacian tensor. - :rtype: LabelTensor - """ - components, d = _check_values( - output_=output_, input_=input_, components=components, d=d - ) - - return fast_laplacian( - output_=output_, - input_=input_, - components=components, - d=d, - method=method, - ) - - -def advection(output_, input_, velocity_field, components=None, d=None): - """ - Perform the advection operation on the ``output_`` with respect to the - ``input``. This operator supports vector-valued functions with multiple - input coordinates. - - :param LabelTensor output_: The output tensor on which the advection is - computed. It includes both the velocity and the quantity to be advected. - :param LabelTensor input_: the input tensor with respect to which advection - is computed. - :param velocity_field: The name of the output variables used as velocity - field. It must be chosen among the output labels. - :type velocity_field: str | list[str] - :param components: The names of the output variables for which to compute - the advection. It must be a subset of the output labels. - If ``None``, all output variables are considered. Default is ``None``. - :type components: str | list[str] - :param d: The names of the input variables with respect to which the - advection is computed. It must be a subset of the input labels. - If ``None``, all input variables are considered. Default is ``None``. - :type d: str | list[str] - :raises TypeError: If the input tensor is not a LabelTensor. - :raises TypeError: If the output tensor is not a LabelTensor. - :raises RuntimeError: If the velocity field is not a subset of the output - labels. - :raises RuntimeError: If the dimensionality of the velocity field does not - match that of the input tensor. - :return: The computed advection tensor. - :rtype: LabelTensor - """ - components, d = _check_values( - output_=output_, input_=input_, components=components, d=d - ) - - # Map velocity_field to a list if it is a string - if isinstance(velocity_field, str): - velocity_field = [velocity_field] - - # Check if all the velocity_field labels are present in the output labels - if not all(vi in output_.labels for vi in velocity_field): - raise RuntimeError("Velocity labels missing from output tensor.") - - # Check if the velocity has the same dimensionality as the input tensor - if len(velocity_field) != len(d): - raise RuntimeError( - "Velocity dimensionality does not match input dimensionality." - ) - - return fast_advection( - output_=output_, - input_=input_, - velocity_field=velocity_field, - components=components, - d=d, - ) +from pina._src.core.operator import ( + grad, + fast_grad, + fast_div, + fast_laplacian, + fast_advection, + div, + laplacian, + advection, +) + +__all__ = [ + "grad", + "fast_grad", + "fast_div", + "fast_laplacian", + "fast_advection", + "div", + "laplacian", + "advection", +] diff --git a/pina/optim/__init__.py b/pina/optim/__init__.py index 8266c8ca1..682b6225e 100644 --- a/pina/optim/__init__.py +++ b/pina/optim/__init__.py @@ -7,7 +7,7 @@ "TorchScheduler", ] -from .optimizer_interface import Optimizer -from .torch_optimizer import TorchOptimizer -from .scheduler_interface import Scheduler -from .torch_scheduler import TorchScheduler +from pina._src.optim.optimizer_interface import Optimizer +from pina._src.optim.torch_optimizer import TorchOptimizer +from pina._src.optim.scheduler_interface import Scheduler +from pina._src.optim.torch_scheduler import TorchScheduler diff --git a/pina/problem/__init__.py b/pina/problem/__init__.py index e95f99703..b170bec21 100644 --- a/pina/problem/__init__.py +++ b/pina/problem/__init__.py @@ -8,8 +8,8 @@ "InverseProblem", ] -from .abstract_problem import AbstractProblem -from .spatial_problem import SpatialProblem -from .time_dependent_problem import TimeDependentProblem -from .parametric_problem import ParametricProblem -from .inverse_problem import InverseProblem +from pina._src.problem.abstract_problem import AbstractProblem +from pina._src.problem.spatial_problem import SpatialProblem +from pina._src.problem.time_dependent_problem import TimeDependentProblem +from pina._src.problem.parametric_problem import ParametricProblem +from pina._src.problem.inverse_problem import InverseProblem diff --git a/pina/problem/zoo.py b/pina/problem/zoo.py new file mode 100644 index 000000000..e5c23ae81 --- /dev/null +++ b/pina/problem/zoo.py @@ -0,0 +1,23 @@ +"""Module for implemented problems.""" + +__all__ = [ + "SupervisedProblem", + "HelmholtzProblem", + "AllenCahnProblem", + "AdvectionProblem", + "Poisson2DSquareProblem", + "DiffusionReactionProblem", + "InversePoisson2DSquareProblem", + "AcousticWaveProblem", +] + +from pina._src.problem.zoo.supervised_problem import SupervisedProblem +from pina._src.problem.zoo.helmholtz import HelmholtzProblem +from pina._src.problem.zoo.allen_cahn import AllenCahnProblem +from pina._src.problem.zoo.advection import AdvectionProblem +from pina._src.problem.zoo.poisson_2d_square import Poisson2DSquareProblem +from pina._src.problem.zoo.diffusion_reaction import DiffusionReactionProblem +from pina._src.problem.zoo.inverse_poisson_2d_square import ( + InversePoisson2DSquareProblem, +) +from pina._src.problem.zoo.acoustic_wave import AcousticWaveProblem diff --git a/pina/problem/zoo/__init__.py b/pina/problem/zoo/__init__.py deleted file mode 100644 index 73e3ad9b6..000000000 --- a/pina/problem/zoo/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -"""Module for implemented problems.""" - -__all__ = [ - "SupervisedProblem", - "HelmholtzProblem", - "AllenCahnProblem", - "AdvectionProblem", - "Poisson2DSquareProblem", - "DiffusionReactionProblem", - "InversePoisson2DSquareProblem", - "AcousticWaveProblem", -] - -from .supervised_problem import SupervisedProblem -from .helmholtz import HelmholtzProblem -from .allen_cahn import AllenCahnProblem -from .advection import AdvectionProblem -from .poisson_2d_square import Poisson2DSquareProblem -from .diffusion_reaction import DiffusionReactionProblem -from .inverse_poisson_2d_square import InversePoisson2DSquareProblem -from .acoustic_wave import AcousticWaveProblem diff --git a/pina/solver/__init__.py b/pina/solver/__init__.py index 43f18078f..a93914099 100644 --- a/pina/solver/__init__.py +++ b/pina/solver/__init__.py @@ -1,4 +1,13 @@ -"""Module for the solver classes.""" +""" +Unified solvers for Physics-Informed and Data-Driven modeling. + +This module provides the high-level training orchestrators used to solve +differential equations and regression problems. It includes: +* **Physics-Informed Solvers**: Standard PINN, Gradient-enhanced (gPINN), Causal, + and Self-Adaptive variants. +* **Supervised Solvers**: For purely data-driven tasks and Reduced Order Modeling. +* **Ensemble Solvers**: For uncertainty quantification via Deep Ensembles. +""" __all__ = [ "SolverInterface", @@ -20,24 +29,38 @@ "GAROM", ] -from .solver import SolverInterface, SingleSolverInterface, MultiSolverInterface -from .physics_informed_solver import ( - PINNInterface, - PINN, - GradientPINN, - CausalPINN, +from pina._src.solver.solver import ( + SolverInterface, + SingleSolverInterface, + MultiSolverInterface, +) +from pina._src.solver.physics_informed_solver.pinn import PINNInterface, PINN +from pina._src.solver.physics_informed_solver.gradient_pinn import GradientPINN +from pina._src.solver.physics_informed_solver.causal_pinn import CausalPINN +from pina._src.solver.physics_informed_solver.competitive_pinn import ( CompetitivePINN, +) +from pina._src.solver.physics_informed_solver.self_adaptive_pinn import ( SelfAdaptivePINN, - RBAPINN, ) -from .supervised_solver import ( +from pina._src.solver.physics_informed_solver.rba_pinn import RBAPINN +from pina._src.solver.supervised_solver.supervised_solver_interface import ( SupervisedSolverInterface, - SupervisedSolver, +) + +from pina._src.solver.supervised_solver.supervised_solver_interface import ( + SupervisedSolverInterface, +) +from pina._src.solver.supervised_solver.supervised import SupervisedSolver +from pina._src.solver.supervised_solver.reduced_order_model import ( ReducedOrderModelSolver, ) -from .ensemble_solver import ( +from pina._src.solver.ensemble_solver.ensemble_solver_interface import ( DeepEnsembleSolverInterface, +) +from pina._src.solver.ensemble_solver.ensemble_pinn import DeepEnsemblePINN +from pina._src.solver.ensemble_solver.ensemble_supervised import ( DeepEnsembleSupervisedSolver, - DeepEnsemblePINN, ) -from .garom import GAROM + +from pina._src.solver.garom import GAROM diff --git a/pina/solver/ensemble_solver/__init__.py b/pina/solver/ensemble_solver/__init__.py deleted file mode 100644 index 0e4eab54b..000000000 --- a/pina/solver/ensemble_solver/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Module for the Ensemble solver classes.""" - -__all__ = [ - "DeepEnsembleSolverInterface", - "DeepEnsembleSupervisedSolver", - "DeepEnsemblePINN", -] - -from .ensemble_solver_interface import DeepEnsembleSolverInterface -from .ensemble_supervised import DeepEnsembleSupervisedSolver -from .ensemble_pinn import DeepEnsemblePINN diff --git a/pina/solver/physics_informed_solver/__init__.py b/pina/solver/physics_informed_solver/__init__.py deleted file mode 100644 index f0fb8ebcd..000000000 --- a/pina/solver/physics_informed_solver/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -"""Module for the Physics-Informed solvers.""" - -__all__ = [ - "PINNInterface", - "PINN", - "GradientPINN", - "CausalPINN", - "CompetitivePINN", - "SelfAdaptivePINN", - "RBAPINN", -] - -from .pinn_interface import PINNInterface -from .pinn import PINN -from .rba_pinn import RBAPINN -from .causal_pinn import CausalPINN -from .gradient_pinn import GradientPINN -from .competitive_pinn import CompetitivePINN -from .self_adaptive_pinn import SelfAdaptivePINN diff --git a/pina/solver/supervised_solver/__init__.py b/pina/solver/supervised_solver/__init__.py deleted file mode 100644 index f681d2dd3..000000000 --- a/pina/solver/supervised_solver/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Module for the Supervised solvers.""" - -__all__ = [ - "SupervisedSolverInterface", - "SupervisedSolver", - "ReducedOrderModelSolver", -] - -from .supervised_solver_interface import SupervisedSolverInterface -from .supervised import SupervisedSolver -from .reduced_order_model import ReducedOrderModelSolver diff --git a/pina/trainer.py b/pina/trainer.py index e92928d1e..5cd598b4c 100644 --- a/pina/trainer.py +++ b/pina/trainer.py @@ -1,362 +1,5 @@ -"""Module for the Trainer.""" +"""Public API for Trainer.""" -import sys -import warnings -import torch -import lightning -from .utils import check_consistency, custom_warning_format -from .data import PinaDataModule -from .solver import SolverInterface, PINNInterface +from pina._src.core.trainer import Trainer -# set the warning for compile options -warnings.formatwarning = custom_warning_format -warnings.filterwarnings("always", category=UserWarning) - - -class Trainer(lightning.pytorch.Trainer): - """ - PINA custom Trainer class to extend the standard Lightning functionality. - - This class enables specific features or behaviors required by the PINA - framework. It modifies the standard - :class:`lightning.pytorch.Trainer ` - class to better support the training process in PINA. - """ - - def __init__( - self, - solver, - batch_size=None, - train_size=1.0, - test_size=0.0, - val_size=0.0, - compile=None, - repeat=None, - automatic_batching=None, - num_workers=None, - pin_memory=None, - shuffle=None, - **kwargs, - ): - """ - Initialization of the :class:`Trainer` class. - - :param SolverInterface solver: A - :class:`~pina.solver.solver.SolverInterface` solver used to solve a - :class:`~pina.problem.abstract_problem.AbstractProblem`. - :param int batch_size: The number of samples per batch to load. - If ``None``, all samples are loaded and data is not batched. - Default is ``None``. - :param float train_size: The percentage of elements to include in the - training dataset. Default is ``1.0``. - :param float test_size: The percentage of elements to include in the - test dataset. Default is ``0.0``. - :param float val_size: The percentage of elements to include in the - validation dataset. Default is ``0.0``. - :param bool compile: If ``True``, the model is compiled before training. - Default is ``False``. For Windows users, it is always disabled. Not - supported for python version greater or equal than 3.14. - :param bool repeat: Whether to repeat the dataset data in each - condition during training. For further details, see the - :class:`~pina.data.data_module.PinaDataModule` class. Default is - ``False``. - :param bool automatic_batching: If ``True``, automatic PyTorch batching - is performed, otherwise the items are retrieved from the dataset - all at once. For further details, see the - :class:`~pina.data.data_module.PinaDataModule` class. Default is - ``False``. - :param int num_workers: The number of worker threads for data loading. - Default is ``0`` (serial loading). - :param bool pin_memory: Whether to use pinned memory for faster data - transfer to GPU. Default is ``False``. - :param bool shuffle: Whether to shuffle the data during training. - Default is ``True``. - :param dict kwargs: Additional keyword arguments that specify the - training setup. These can be selected from the `pytorch-lightning - Trainer API - `_. - """ - # check consistency for init types - self._check_input_consistency( - solver=solver, - train_size=train_size, - test_size=test_size, - val_size=val_size, - repeat=repeat, - automatic_batching=automatic_batching, - compile=compile, - ) - pin_memory, num_workers, shuffle, batch_size = ( - self._check_consistency_and_set_defaults( - pin_memory, num_workers, shuffle, batch_size - ) - ) - - # inference mode set to false when validating/testing PINNs otherwise - # gradient is not tracked and optimization_cycle fails - if isinstance(solver, PINNInterface): - kwargs["inference_mode"] = False - - # Logging depends on the batch size, when batch_size is None then - # log_every_n_steps should be zero - if batch_size is None: - kwargs["log_every_n_steps"] = 0 - else: - kwargs.setdefault("log_every_n_steps", 50) # default for lightning - - # Setting default kwargs, overriding lightning defaults - kwargs.setdefault("enable_progress_bar", True) - - super().__init__(**kwargs) - - # checking compilation and automatic batching - # compilation disabled for Windows and for Python 3.14+ - if ( - compile is None - or sys.platform == "win32" - or sys.version_info >= (3, 14) - ): - compile = False - warnings.warn( - "Compilation is disabled for Python 3.14+ and for Windows.", - UserWarning, - ) - - repeat = repeat if repeat is not None else False - - automatic_batching = ( - automatic_batching if automatic_batching is not None else False - ) - - # set attributes - self.compile = compile - self.solver = solver - self.batch_size = batch_size - self._move_to_device() - self.data_module = None - self._create_datamodule( - train_size=train_size, - test_size=test_size, - val_size=val_size, - batch_size=batch_size, - repeat=repeat, - automatic_batching=automatic_batching, - pin_memory=pin_memory, - num_workers=num_workers, - shuffle=shuffle, - ) - - # logging - self.logging_kwargs = { - "sync_dist": bool( - len(self._accelerator_connector._parallel_devices) > 1 - ), - "on_step": bool(kwargs["log_every_n_steps"] > 0), - "prog_bar": bool(kwargs["enable_progress_bar"]), - "on_epoch": True, - } - - def _move_to_device(self): - """ - Moves the ``unknown_parameters`` of an instance of - :class:`~pina.problem.abstract_problem.AbstractProblem` to the - :class:`Trainer` device. - """ - device = self._accelerator_connector._parallel_devices[0] - # move parameters to device - pb = self.solver.problem - if hasattr(pb, "unknown_parameters"): - for key in pb.unknown_parameters: - pb.unknown_parameters[key] = torch.nn.Parameter( - pb.unknown_parameters[key].data.to(device) - ) - - def _create_datamodule( - self, - train_size, - test_size, - val_size, - batch_size, - repeat, - automatic_batching, - pin_memory, - num_workers, - shuffle, - ): - """ - This method is designed to handle the creation of a data module when - resampling is needed during training. Instead of manually defining and - modifying the trainer's dataloaders, this method is called to - automatically configure the data module. - - :param float train_size: The percentage of elements to include in the - training dataset. - :param float test_size: The percentage of elements to include in the - test dataset. - :param float val_size: The percentage of elements to include in the - validation dataset. - :param int batch_size: The number of samples per batch to load. - :param bool repeat: Whether to repeat the dataset data in each - condition during training. - :param bool automatic_batching: Whether to perform automatic batching - with PyTorch. - :param bool pin_memory: Whether to use pinned memory for faster data - transfer to GPU. - :param int num_workers: The number of worker threads for data loading. - :param bool shuffle: Whether to shuffle the data during training. - :raises RuntimeError: If not all conditions are sampled. - """ - if not self.solver.problem.are_all_domains_discretised: - error_message = "\n".join( - [ - f"""{" " * 13} ---> Domain {key} { - "sampled" if key in self.solver.problem.discretised_domains - else - "not sampled"}""" - for key in self.solver.problem.domains.keys() - ] - ) - raise RuntimeError( - "Cannot create Trainer if not all conditions " - "are sampled. The Trainer got the following:\n" - f"{error_message}" - ) - self.data_module = PinaDataModule( - self.solver.problem, - train_size=train_size, - test_size=test_size, - val_size=val_size, - batch_size=batch_size, - repeat=repeat, - automatic_batching=automatic_batching, - num_workers=num_workers, - pin_memory=pin_memory, - shuffle=shuffle, - ) - - def train(self, **kwargs): - """ - Manage the training process of the solver. - - :param dict kwargs: Additional keyword arguments. See `pytorch-lightning - Trainer API `_ - for details. - """ - return super().fit(self.solver, datamodule=self.data_module, **kwargs) - - def test(self, **kwargs): - """ - Manage the test process of the solver. - - :param dict kwargs: Additional keyword arguments. See `pytorch-lightning - Trainer API `_ - for details. - """ - return super().test(self.solver, datamodule=self.data_module, **kwargs) - - @property - def solver(self): - """ - Get the solver. - - :return: The solver. - :rtype: SolverInterface - """ - return self._solver - - @solver.setter - def solver(self, solver): - """ - Set the solver. - - :param SolverInterface solver: The solver to set. - """ - self._solver = solver - - @staticmethod - def _check_input_consistency( - solver, - train_size, - test_size, - val_size, - repeat, - automatic_batching, - compile, - ): - """ - Verifies the consistency of the parameters for the solver configuration. - - :param SolverInterface solver: The solver. - :param float train_size: The percentage of elements to include in the - training dataset. - :param float test_size: The percentage of elements to include in the - test dataset. - :param float val_size: The percentage of elements to include in the - validation dataset. - :param bool repeat: Whether to repeat the dataset data in each - condition during training. - :param bool automatic_batching: Whether to perform automatic batching - with PyTorch. - :param bool compile: If ``True``, the model is compiled before training. - """ - - check_consistency(solver, SolverInterface) - check_consistency(train_size, float) - check_consistency(test_size, float) - check_consistency(val_size, float) - if repeat is not None: - check_consistency(repeat, bool) - if automatic_batching is not None: - check_consistency(automatic_batching, bool) - if compile is not None: - check_consistency(compile, bool) - - @staticmethod - def _check_consistency_and_set_defaults( - pin_memory, num_workers, shuffle, batch_size - ): - """ - Checks the consistency of input parameters and sets default values - for missing or invalid parameters. - - :param bool pin_memory: Whether to use pinned memory for faster data - transfer to GPU. - :param int num_workers: The number of worker threads for data loading. - :param bool shuffle: Whether to shuffle the data during training. - :param int batch_size: The number of samples per batch to load. - """ - if pin_memory is not None: - check_consistency(pin_memory, bool) - else: - pin_memory = False - if num_workers is not None: - check_consistency(num_workers, int) - else: - num_workers = 0 - if shuffle is not None: - check_consistency(shuffle, bool) - else: - shuffle = True - if batch_size is not None: - check_consistency(batch_size, int) - return pin_memory, num_workers, shuffle, batch_size - - @property - def compile(self): - """ - Whether compilation is required or not. - - :return: ``True`` if compilation is required, ``False`` otherwise. - :rtype: bool - """ - return self._compile - - @compile.setter - def compile(self, value): - """ - Setting the value of compile. - - :param bool value: Whether compilation is required or not. - """ - check_consistency(value, bool) - self._compile = value +__all__ = ["Trainer"] diff --git a/pina/type_checker.py b/pina/type_checker.py index e8c908ac9..cfa886da3 100644 --- a/pina/type_checker.py +++ b/pina/type_checker.py @@ -1,93 +1,11 @@ -"""Module for enforcing type hints in Python functions.""" +"""Runtime type enforcement and validation utilities. -import inspect -import typing -import logging +This module provides decorators to validate function arguments against type +annotations at runtime. This ensures that PINA components receive inputs +adhering to expected specifications, improving the robustness of the +scientific computing pipeline. +""" +from pina._src.core.type_checker import enforce_types -def enforce_types(func): - """ - Function decorator to enforce type hints at runtime. - - This decorator checks the types of the arguments and of the return value of - the decorated function against the type hints specified in the function - signature. If the types do not match, a TypeError is raised. - Type checking is only performed when the logging level is set to `DEBUG`. - - :param Callable func: The function to be decorated. - :return: The decorated function with enforced type hints. - :rtype: Callable - - :Example: - - >>> @enforce_types - def dummy_function(a: int, b: float) -> float: - ... return a+b - - # This always works. - dummy_function(1, 2.0) - - # This raises a TypeError for the second argument, if logging is set to - # `DEBUG`. - dummy_function(1, "Hello, world!") - - - >>> @enforce_types - def dummy_function2(a: int, right: bool) -> float: - ... if right: - ... return float(a) - ... else: - ... return "Hello, world!" - - # This always works. - dummy_function2(1, right=True) - - # This raises a TypeError for the return value if logging is set to - # `DEBUG`. - dummy_function2(1, right=False) - """ - - def wrapper(*args, **kwargs): - """ - Wrapper function to enforce type hints. - - :param tuple args: Positional arguments passed to the function. - :param dict kwargs: Keyword arguments passed to the function. - :raises TypeError: If the argument or return type does not match the - specified type hints. - :return: The result of the decorated function. - :rtype: Any - """ - level = logging.getLevelName(logging.getLogger().getEffectiveLevel()) - - # Enforce type hints only in debug mode - if level != "DEBUG": - return func(*args, **kwargs) - - # Get the type hints for the function arguments - hints = typing.get_type_hints(func) - sig = inspect.signature(func) - bound = sig.bind(*args, **kwargs) - bound.apply_defaults() - - for arg_name, arg_value in bound.arguments.items(): - expected_type = hints.get(arg_name) - if expected_type and not isinstance(arg_value, expected_type): - raise TypeError( - f"Argument '{arg_name}' must be {expected_type.__name__}, " - f"but got {type(arg_value).__name__}!" - ) - - # Get the type hints for the return values - return_type = hints.get("return") - result = func(*args, **kwargs) - - if return_type and not isinstance(result, return_type): - raise TypeError( - f"Return value must be {return_type.__name__}, " - f"but got {type(result).__name__}!" - ) - - return result - - return wrapper +__all__ = ["enforce_types"] diff --git a/pina/utils.py b/pina/utils.py index efc48424e..8e40ae9cd 100644 --- a/pina/utils.py +++ b/pina/utils.py @@ -1,270 +1,19 @@ -"""Module for utility functions.""" - -import types -from functools import reduce -import torch - -from .label_tensor import LabelTensor - - -# Codacy error unused parameters -def custom_warning_format( - message, category, filename, lineno, file=None, line=None -): - """ - Custom warning formatting function. - - :param str message: The warning message. - :param Warning category: The warning category. - :param str filename: The filename where the warning is raised. - :param int lineno: The line number where the warning is raised. - :param str file: The file object where the warning is raised. - Default is None. - :param int line: The line where the warning is raised. - :return: The formatted warning message. - :rtype: str - """ - return f"{filename}: {category.__name__}: {message}\n" - - -def check_consistency(object_, object_instance, subclass=False): - """ - Check if an object maintains inheritance consistency. - - This function checks whether a given object is an instance of a specified - class or, if ``subclass=True``, whether it is a subclass of the specified - class. - - :param object: The object to check. - :type object: Iterable | Object - :param Object object_instance: The expected parent class. - :param bool subclass: If True, checks whether ``object_`` is a subclass - of ``object_instance`` instead of an instance. Default is ``False``. - :raises ValueError: If ``object_`` does not inherit from ``object_instance`` - as expected. - """ - if not isinstance(object_, (list, set, tuple)): - object_ = [object_] - - for obj in object_: - is_class = isinstance(obj, type) - expected_type_name = ( - object_instance.__name__ - if isinstance(object_instance, type) - else str(object_instance) - ) - - if subclass: - if not is_class: - raise ValueError( - f"You passed {repr(obj)} " - f"(an instance of {type(obj).__name__}), " - f"but a {expected_type_name} class was expected. " - f"Please pass a {expected_type_name} class or a " - "derived one." - ) - if not issubclass(obj, object_instance): - raise ValueError( - f"You passed {obj.__name__} class, but a " - f"{expected_type_name} class was expected. " - f"Please pass a {expected_type_name} class or a " - "derived one." - ) - else: - if is_class: - raise ValueError( - f"You passed {obj.__name__} class, but a " - f"{expected_type_name} instance was expected. " - f"Please pass a {expected_type_name} instance." - ) - if not isinstance(obj, object_instance): - raise ValueError( - f"You passed {repr(obj)} " - f"(an instance of {type(obj).__name__}), " - f"but a {expected_type_name} instance was expected. " - f"Please pass a {expected_type_name} instance." - ) - - -def labelize_forward(forward, input_variables, output_variables): - """ - Decorator to enable or disable the use of - :class:`~pina.label_tensor.LabelTensor` during the forward pass. - - :param Callable forward: The forward function of a :class:`torch.nn.Module`. - :param list[str] input_variables: The names of the input variables of a - :class:`~pina.problem.abstract_problem.AbstractProblem`. - :param list[str] output_variables: The names of the output variables of a - :class:`~pina.problem.abstract_problem.AbstractProblem`. - :return: The decorated forward function. - :rtype: Callable - """ - - def wrapper(x, *args, **kwargs): - """ - Decorated forward function. - - :param LabelTensor x: The labelized input of the forward pass of an - instance of :class:`torch.nn.Module`. - :param Iterable args: Additional positional arguments passed to - ``forward`` method. - :param dict kwargs: Additional keyword arguments passed to - ``forward`` method. - :return: The labelized output of the forward pass of an instance of - :class:`torch.nn.Module`. - :rtype: LabelTensor - """ - x = x.extract(input_variables) - output = forward(x, *args, **kwargs) - # keep it like this, directly using LabelTensor(...) raises errors - # when compiling the code - output = output.as_subclass(LabelTensor) - output.labels = output_variables - return output - - return wrapper - - -def merge_tensors(tensors): - """ - Merge a list of :class:`~pina.label_tensor.LabelTensor` instances into a - single :class:`~pina.label_tensor.LabelTensor` tensor, by applying - iteratively the cartesian product. - - :param list[LabelTensor] tensors: The list of tensors to merge. - :raises ValueError: If the list of tensors is empty. - :return: The merged tensor. - :rtype: LabelTensor - """ - if tensors: - return reduce(merge_two_tensors, tensors[1:], tensors[0]) - raise ValueError("Expected at least one tensor") - - -def merge_two_tensors(tensor1, tensor2): - """ - Merge two :class:`~pina.label_tensor.LabelTensor` instances into a single - :class:`~pina.label_tensor.LabelTensor` tensor, by applying the cartesian - product. - - :param LabelTensor tensor1: The first tensor to merge. - :param LabelTensor tensor2: The second tensor to merge. - :return: The merged tensor. - :rtype: LabelTensor - """ - n1 = tensor1.shape[0] - n2 = tensor2.shape[0] - - tensor1 = LabelTensor(tensor1.repeat(n2, 1), labels=tensor1.labels) - tensor2 = LabelTensor( - tensor2.repeat_interleave(n1, dim=0), labels=tensor2.labels - ) - return tensor1.append(tensor2) - - -def torch_lhs(n, dim): - """ - The Latin Hypercube Sampling torch routine, sampling in :math:`[0, 1)`$. - - :param int n: The number of points to sample. - :param int dim: The number of dimensions of the sampling space. - :raises TypeError: If `n` or `dim` are not integers. - :raises ValueError: If `dim` is less than 1. - :return: The sampled points. - :rtype: torch.tensor - """ - - if not isinstance(n, int): - raise TypeError("number of point n must be int") - - if not isinstance(dim, int): - raise TypeError("dim must be int") - - if dim < 1: - raise ValueError("dim must be greater than one") - - samples = torch.rand(size=(n, dim)) - - perms = torch.tile(torch.arange(1, n + 1), (dim, 1)) - - for row in range(dim): - idx_perm = torch.randperm(perms.shape[-1]) - perms[row, :] = perms[row, idx_perm] - - perms = perms.T - - samples = (perms - samples) / n - - return samples - - -def is_function(f): - """ - Check if the given object is a function or a lambda. - - :param Object f: The object to be checked. - :return: ``True`` if ``f`` is a function, ``False`` otherwise. - :rtype: bool - """ - return callable(f) - - -def chebyshev_roots(n): - """ - Compute the roots of the Chebyshev polynomial of degree ``n``. - - :param int n: The number of roots to return. - :return: The roots of the Chebyshev polynomials. - :rtype: torch.Tensor - """ - pi = torch.acos(torch.zeros(1)).item() * 2 - k = torch.arange(n) - nodes = torch.sort(torch.cos(pi * (k + 0.5) / n))[0] - return nodes - - -def check_positive_integer(value, strict=True): - """ - Check if the value is a positive integer. - - :param int value: The value to check. - :param bool strict: If True, the value must be strictly positive. - Default is True. - :raises AssertionError: If the value is not a positive integer. - """ - if strict: - assert ( - isinstance(value, int) and value > 0 - ), f"Expected a strictly positive integer, got {value}." - else: - assert ( - isinstance(value, int) and value >= 0 - ), f"Expected a non-negative integer, got {value}." - - -def in_range(value, range_vals, strict=True): - """ - Check if a value is within a specified range. - - :param int value: The integer value to check. - :param list[int] range_vals: A list of two integers representing the range - limits. The first element specifies the lower bound, and the second - specifies the upper bound. - :param bool strict: If True, the value must be strictly positive. - Default is True. - :return: True if the value satisfies the range condition, False otherwise. - :rtype: bool - """ - # Validate inputs - check_consistency(value, (float, int)) - check_consistency(range_vals, (float, int)) - assert ( - isinstance(range_vals, list) and len(range_vals) == 2 - ), "range_vals must be a list of two integers [lower, upper]" - lower, upper = range_vals - - # Check the range - if strict: - return lower < value < upper - - return lower <= value <= upper +""" +Utility functions for tensor manipulation and input validation. + +This module provides helper functions to manage tensor operations and ensure +data consistency across the PINA framework, supporting robust input checking +and seamless data merging. +""" + +from pina._src.core.utils import ( + merge_tensors, + check_consistency, + check_positive_integer, +) + +__all__ = [ + "merge_tensors", + "check_consistency", + "check_positive_integer", +] diff --git a/tests/test_adaptive_function.py b/tests/test_adaptive_function.py index bce5059d7..fae547ffb 100644 --- a/tests/test_adaptive_function.py +++ b/tests/test_adaptive_function.py @@ -16,7 +16,6 @@ AdaptiveExp, ) - adaptive_function = ( AdaptiveReLU, AdaptiveSigmoid, diff --git a/tests/test_block/test_low_rank_block.py b/tests/test_block/test_low_rank_block.py index 0e6ddcb89..17f0dabd6 100644 --- a/tests/test_block/test_low_rank_block.py +++ b/tests/test_block/test_low_rank_block.py @@ -4,7 +4,6 @@ from pina.model.block import LowRankBlock from pina import LabelTensor - input_dimensions = 2 embedding_dimenion = 1 rank = 4 diff --git a/tests/test_block/test_pod.py b/tests/test_block/test_pod.py index d10625fc3..ffe9a8a81 100644 --- a/tests/test_block/test_pod.py +++ b/tests/test_block/test_pod.py @@ -1,7 +1,7 @@ import torch import pytest -from pina.model.block.pod_block import PODBlock +from pina.model.block import PODBlock x = torch.linspace(-1, 1, 100) toy_snapshots = torch.vstack( diff --git a/tests/test_block/test_rbf.py b/tests/test_block/test_rbf.py index 65912fb76..c36836743 100644 --- a/tests/test_block/test_rbf.py +++ b/tests/test_block/test_rbf.py @@ -2,7 +2,7 @@ import pytest import math -from pina.model.block.rbf_block import RBFBlock +from pina.model.block import RBFBlock x = torch.linspace(-1, 1, 100) toy_params = torch.linspace(0, 1, 10).unsqueeze(1) diff --git a/tests/test_callback/test_metric_tracker.py b/tests/test_callback/test_metric_tracker.py index 062664b79..49b904885 100644 --- a/tests/test_callback/test_metric_tracker.py +++ b/tests/test_callback/test_metric_tracker.py @@ -4,7 +4,6 @@ from pina.callback import MetricTracker from pina.problem.zoo import Poisson2DSquareProblem as Poisson - # make the problem poisson_problem = Poisson() n = 10 diff --git a/tests/test_callback/test_pina_progress_bar.py b/tests/test_callback/test_pina_progress_bar.py index ec7129852..8956ebaf0 100644 --- a/tests/test_callback/test_pina_progress_bar.py +++ b/tests/test_callback/test_pina_progress_bar.py @@ -4,7 +4,6 @@ from pina.callback import PINAProgressBar from pina.problem.zoo import Poisson2DSquareProblem as Poisson - # make the problem poisson_problem = Poisson() n = 10 diff --git a/tests/test_callback/test_r3_refinement.py b/tests/test_callback/test_r3_refinement.py index 191266ee1..f8b9519e9 100644 --- a/tests/test_callback/test_r3_refinement.py +++ b/tests/test_callback/test_r3_refinement.py @@ -6,7 +6,6 @@ from pina.problem.zoo import Poisson2DSquareProblem as Poisson from pina.callback import R3Refinement - # make the problem poisson_problem = Poisson() poisson_problem.discretise_domain(10, "grid", domains="boundary") diff --git a/tests/test_callback/test_switch_optimizer.py b/tests/test_callback/test_switch_optimizer.py index 3383c792c..c7490a231 100644 --- a/tests/test_callback/test_switch_optimizer.py +++ b/tests/test_callback/test_switch_optimizer.py @@ -8,7 +8,6 @@ from pina.callback import SwitchOptimizer from pina.problem.zoo import Poisson2DSquareProblem as Poisson - # Define the problem problem = Poisson() problem.discretise_domain(10) diff --git a/tests/test_callback/test_switch_scheduler.py b/tests/test_callback/test_switch_scheduler.py index df91f0c59..36b177853 100644 --- a/tests/test_callback/test_switch_scheduler.py +++ b/tests/test_callback/test_switch_scheduler.py @@ -8,7 +8,6 @@ from pina.callback import SwitchScheduler from pina.problem.zoo import Poisson2DSquareProblem as Poisson - # Define the problem problem = Poisson() problem.discretise_domain(10) diff --git a/tests/test_condition.py b/tests/test_condition.py index 9199f2bd9..266233179 100644 --- a/tests/test_condition.py +++ b/tests/test_condition.py @@ -18,7 +18,7 @@ GraphDataCondition, ) from pina.domain import CartesianDomain -from pina.equation.equation_factory import FixedValue +from pina.equation import FixedValue from pina.graph import RadiusGraph example_domain = CartesianDomain({"x": [0, 1], "y": [0, 1]}) diff --git a/tests/test_data/test_data_module.py b/tests/test_data/test_data_module.py index 53e7334ec..9fd2d36ee 100644 --- a/tests/test_data/test_data_module.py +++ b/tests/test_data/test_data_module.py @@ -1,10 +1,10 @@ import torch import pytest from pina.data import PinaDataModule -from pina.data.dataset import PinaTensorDataset, PinaGraphDataset +from pina.data import PinaTensorDataset, PinaGraphDataset from pina.problem.zoo import SupervisedProblem from pina.graph import RadiusGraph -from pina.data.data_module import DummyDataloader +from pina.data import DummyDataloader from pina import Trainer from pina.solver import SupervisedSolver from torch_geometric.data import Batch diff --git a/tests/test_data/test_graph_dataset.py b/tests/test_data/test_graph_dataset.py index 81d6a2c5d..3a63f7ec6 100644 --- a/tests/test_data/test_graph_dataset.py +++ b/tests/test_data/test_graph_dataset.py @@ -1,6 +1,6 @@ import torch import pytest -from pina.data.dataset import PinaDatasetFactory, PinaGraphDataset +from pina.data import PinaDatasetFactory, PinaGraphDataset from pina.graph import KNNGraph from torch_geometric.data import Data diff --git a/tests/test_data/test_tensor_dataset.py b/tests/test_data/test_tensor_dataset.py index 81a122f2f..9e348c942 100644 --- a/tests/test_data/test_tensor_dataset.py +++ b/tests/test_data/test_tensor_dataset.py @@ -1,6 +1,6 @@ import torch import pytest -from pina.data.dataset import PinaDatasetFactory, PinaTensorDataset +from pina.data import PinaDatasetFactory, PinaTensorDataset input_tensor = torch.rand((100, 10)) output_tensor = torch.rand((100, 2)) diff --git a/tests/test_label_tensor/test_label_tensor.py b/tests/test_label_tensor/test_label_tensor.py index 973864d0e..ca4ae2f1a 100644 --- a/tests/test_label_tensor/test_label_tensor.py +++ b/tests/test_label_tensor/test_label_tensor.py @@ -1,7 +1,7 @@ import torch import pytest -from pina.label_tensor import LabelTensor +from pina import LabelTensor data = torch.rand((20, 3)) labels_column = {1: {"name": "space", "dof": ["x", "y", "z"]}} diff --git a/tests/test_loss/test_power_loss.py b/tests/test_loss/test_power_loss.py index 4ea90282b..3781f66d3 100644 --- a/tests/test_loss/test_power_loss.py +++ b/tests/test_loss/test_power_loss.py @@ -1,5 +1,4 @@ import torch -import pytest from pina.loss import PowerLoss diff --git a/tests/test_model/test_average_neural_operator.py b/tests/test_model/test_average_neural_operator.py index ded81c43d..4a7ecb44b 100644 --- a/tests/test_model/test_average_neural_operator.py +++ b/tests/test_model/test_average_neural_operator.py @@ -3,7 +3,6 @@ from pina import LabelTensor import pytest - batch_size = 15 n_layers = 4 embedding_dim = 24 diff --git a/tests/test_model/test_low_rank_neural_operator.py b/tests/test_model/test_low_rank_neural_operator.py index 3702df91b..ba4b2fffe 100644 --- a/tests/test_model/test_low_rank_neural_operator.py +++ b/tests/test_model/test_low_rank_neural_operator.py @@ -3,7 +3,6 @@ from pina import LabelTensor import pytest - batch_size = 15 n_layers = 4 embedding_dim = 24 diff --git a/tests/test_model/test_spline.py b/tests/test_model/test_spline.py index b47ea8d30..baff81940 100644 --- a/tests/test_model/test_spline.py +++ b/tests/test_model/test_spline.py @@ -5,7 +5,6 @@ from pina.model import Spline from pina import LabelTensor - # Utility quantities for testing order = torch.randint(3, 6, (1,)).item() n_ctrl_pts = torch.randint(order, order + 5, (1,)).item() diff --git a/tests/test_model/test_spline_surface.py b/tests/test_model/test_spline_surface.py index dee57173c..4cd6dc3aa 100644 --- a/tests/test_model/test_spline_surface.py +++ b/tests/test_model/test_spline_surface.py @@ -5,7 +5,6 @@ from pina.operator import grad from pina import LabelTensor - # Utility quantities for testing orders = [random.randint(3, 6) for _ in range(2)] n_ctrl_pts = random.randint(max(orders), max(orders) + 5) diff --git a/tests/test_problem_zoo/test_supervised_problem.py b/tests/test_problem_zoo/test_supervised_problem.py index 19b3920ce..da18d6146 100644 --- a/tests/test_problem_zoo/test_supervised_problem.py +++ b/tests/test_problem_zoo/test_supervised_problem.py @@ -1,7 +1,7 @@ import torch from pina.problem import AbstractProblem from pina.condition import InputTargetCondition -from pina.problem.zoo.supervised_problem import SupervisedProblem +from pina.problem.zoo import SupervisedProblem from pina.graph import RadiusGraph diff --git a/tests/test_solver/test_competitive_pinn.py b/tests/test_solver/test_competitive_pinn.py index 8f585f029..67902197a 100644 --- a/tests/test_solver/test_competitive_pinn.py +++ b/tests/test_solver/test_competitive_pinn.py @@ -16,7 +16,6 @@ ) from torch._dynamo.eval_frame import OptimizedModule - # define problems problem = Poisson() problem.discretise_domain(10) diff --git a/tests/test_solver/test_ensemble_pinn.py b/tests/test_solver/test_ensemble_pinn.py index 50669f00e..e34ad3643 100644 --- a/tests/test_solver/test_ensemble_pinn.py +++ b/tests/test_solver/test_ensemble_pinn.py @@ -13,7 +13,6 @@ from pina.problem.zoo import Poisson2DSquareProblem as Poisson from torch._dynamo.eval_frame import OptimizedModule - # define problems problem = Poisson() problem.discretise_domain(10) diff --git a/tests/test_solver/test_pinn.py b/tests/test_solver/test_pinn.py index d726047ef..76094b473 100644 --- a/tests/test_solver/test_pinn.py +++ b/tests/test_solver/test_pinn.py @@ -16,7 +16,6 @@ ) from torch._dynamo.eval_frame import OptimizedModule - # define problems problem = Poisson() problem.discretise_domain(10) diff --git a/tests/test_solver/test_self_adaptive_pinn.py b/tests/test_solver/test_self_adaptive_pinn.py index b2d1361ca..244f10d4f 100644 --- a/tests/test_solver/test_self_adaptive_pinn.py +++ b/tests/test_solver/test_self_adaptive_pinn.py @@ -16,7 +16,6 @@ ) from torch._dynamo.eval_frame import OptimizedModule - # define problems problem = Poisson() problem.discretise_domain(10) diff --git a/tests/test_weighting/test_linear_weighting.py b/tests/test_weighting/test_linear_weighting.py index a11952073..db5e8a9ac 100644 --- a/tests/test_weighting/test_linear_weighting.py +++ b/tests/test_weighting/test_linear_weighting.py @@ -6,7 +6,6 @@ from pina.loss import LinearWeighting from pina.problem.zoo import Poisson2DSquareProblem - # Initialize problem and model problem = Poisson2DSquareProblem() problem.discretise_domain(10) diff --git a/tests/test_weighting/test_ntk_weighting.py b/tests/test_weighting/test_ntk_weighting.py index 49442b9fb..f908ae538 100644 --- a/tests/test_weighting/test_ntk_weighting.py +++ b/tests/test_weighting/test_ntk_weighting.py @@ -5,7 +5,6 @@ from pina.loss import NeuralTangentKernelWeighting from pina.problem.zoo import Poisson2DSquareProblem - # Initialize problem and model problem = Poisson2DSquareProblem() problem.discretise_domain(10) diff --git a/tests/test_weighting/test_scalar_weighting.py b/tests/test_weighting/test_scalar_weighting.py index bbf71afde..395cdbcc0 100644 --- a/tests/test_weighting/test_scalar_weighting.py +++ b/tests/test_weighting/test_scalar_weighting.py @@ -6,7 +6,6 @@ from pina.loss import ScalarWeighting from pina.problem.zoo import Poisson2DSquareProblem - # Initialize problem and model problem = Poisson2DSquareProblem() problem.discretise_domain(50) diff --git a/tests/test_weighting/test_self_adaptive_weighting.py b/tests/test_weighting/test_self_adaptive_weighting.py index 066e8855e..e11aff14c 100644 --- a/tests/test_weighting/test_self_adaptive_weighting.py +++ b/tests/test_weighting/test_self_adaptive_weighting.py @@ -5,7 +5,6 @@ from pina.loss import SelfAdaptiveWeighting from pina.problem.zoo import Poisson2DSquareProblem - # Initialize problem and model problem = Poisson2DSquareProblem() problem.discretise_domain(10)