@@ -556,23 +556,37 @@ end
556556 check_node(n::Node, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
557557
558558Check that the fields of a `Node` corresponds to required structure.
559+
560+ The default approach calls the subroutine [`check_node_default`](@ref) which provides the
561+ user with default checks for [`Source`](@ref), [`NetworkNode`](@ref), [`Availability`](@ref),
562+ [`Storage`](@ref), and [`Sink`](@ref) nodes.
563+
564+ !!! tip "Creating a new node type"
565+ When developing a new node with new checks, it is important to create a new method for
566+ `check_node`. You can then call within this function the default tests for the corresponding
567+ supertype through calling the function [`check_node_default`](@ref).
559568"""
560- function check_node (n:: Node , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool ) end
569+ check_node (n:: Node , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool ) =
570+ check_node_default (n, 𝒯, modeltype, check_timeprofiles)
561571"""
562- check_node (n::Availability , 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
572+ check_node_default (n::Node , 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
563573
564- This method checks that an `Availability ` node is valid. By default, that does not include
574+ This method checks that a `Node ` node is valid. By default, that does not include
565575any checks.
566576"""
567- function check_node (n:: Availability , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool ) end
577+ function check_node_default (n:: Node , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool ) end
568578"""
569- check_node (n::Source , 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
579+ check_node_default (n::Availability , 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
570580
571- This method checks that a `Source` node is valid.
581+ This method checks that an `Availability` node is valid. By default, that does not include
582+ any checks.
583+ """
584+ function check_node_default (n:: Availability , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool ) end
585+ """
586+ check_node_default(n::Source, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
572587
573- These checks are always performed, if the user is not creating a new method. Hence, it is
574- important that a new `Source` type includes at least the same fields as in the [`RefSource`](@ref)
575- node or that a new `Source` type receives a new method for `check_node`.
588+ Subroutine that can be utilized in other packages for incorporating the standard tests for
589+ a [`Source`](@ref) node.
576590
577591## Checks
578592- The field `cap` is required to be non-negative.
@@ -581,27 +595,24 @@ node or that a new `Source` type receives a new method for `check_node`.
581595 accessible through a `StrategicPeriod` as outlined in the function
582596 [`check_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles)`](@ref).
583597"""
584- function check_node (n:: Source , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
598+ function check_node_default (n:: Source , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
585599 𝒯ᴵⁿᵛ = strategic_periods (𝒯)
586600
587601 @assert_or_log (
588- sum (capacity (n, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
602+ all (capacity (n, t) ≥ 0 for t ∈ 𝒯),
589603 " The capacity must be non-negative."
590604 )
591605 @assert_or_log (
592- sum (outputs (n, p) ≥ 0 for p ∈ outputs (n)) == length ( outputs (n)),
606+ all (outputs (n, p) ≥ 0 for p ∈ outputs (n)),
593607 " The values for the Dictionary `output` must be non-negative."
594608 )
595609 check_fixed_opex (n, 𝒯ᴵⁿᵛ, check_timeprofiles)
596610end
597611"""
598- check_node(n::NetworkNode, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
599-
600- This method checks that a `NetworkNode` node is valid.
612+ check_node_default(n::NetworkNode, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
601613
602- These checks are always performed, if the user is not creating a new method. Hence, it is
603- important that a new `NetworkNode` type includes at least the same fields as in the
604- [`RefNetworkNode`(@ref) node or that a new `NetworkNode` type receives a new method for `check_node`.
614+ Subroutine that can be utilized in other packages for incorporating the standard tests for
615+ a [`NetworkNode`](@ref) node.
605616
606617## Checks
607618- The field `cap` is required to be non-negative.
@@ -611,31 +622,28 @@ important that a new `NetworkNode` type includes at least the same fields as in
611622 accessible through a `StrategicPeriod` as outlined in the function
612623 [`check_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles)`](@ref).
613624"""
614- function check_node (n:: NetworkNode , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
625+ function check_node_default (n:: NetworkNode , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
615626 𝒯ᴵⁿᵛ = strategic_periods (𝒯)
616627
617628 @assert_or_log (
618- sum (capacity (n, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
629+ all (capacity (n, t) ≥ 0 for t ∈ 𝒯),
619630 " The capacity must be non-negative."
620631 )
621632 @assert_or_log (
622- sum (inputs (n, p) ≥ 0 for p ∈ inputs (n)) == length ( inputs (n)),
633+ all (inputs (n, p) ≥ 0 for p ∈ inputs (n)),
623634 " The values for the Dictionary `input` must be non-negative."
624635 )
625636 @assert_or_log (
626- sum (outputs (n, p) ≥ 0 for p ∈ outputs (n)) == length ( outputs (n)),
637+ all (outputs (n, p) ≥ 0 for p ∈ outputs (n)),
627638 " The values for the Dictionary `output` must be non-negative."
628639 )
629640 check_fixed_opex (n, 𝒯ᴵⁿᵛ, check_timeprofiles)
630641end
631642"""
632- check_node (n::Storage, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
643+ check_node_default (n::Storage, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
633644
634- This method checks that a `Storage` node is valid.
635-
636- These checks are always performed, if the user is not creating a new method. Hence, it is
637- important that a new `Storage` type includes at least the same fields as in the
638- [`RefStorage`](@ref) node or that a new `Storage` type receives a new method for `check_node`.
645+ Subroutine that can be utilized in other packages for incorporating the standard tests for
646+ a [`Storage`](@ref) node.
639647
640648## Checks
641649- The `TimeProfile` of the field `capacity` in the type in the field `charge` is required
@@ -650,69 +658,67 @@ important that a new `Storage` type includes at least the same fields as in the
650658- The values of the dictionary `input` are required to be non-negative.
651659- The values of the dictionary `output` are required to be non-negative.
652660"""
653- function check_node (n:: Storage , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
661+ function check_node_default (n:: Storage , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
654662 𝒯ᴵⁿᵛ = strategic_periods (𝒯)
655663 par_charge = charge (n)
656664 par_level = level (n)
657665 par_discharge = discharge (n)
658666
659667 if isa (par_charge, UnionCapacity)
660668 @assert_or_log (
661- sum (capacity (par_charge, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
669+ all (capacity (par_charge, t) ≥ 0 for t ∈ 𝒯),
662670 " The charge capacity must be non-negative."
663671 )
664672 end
665673 if isa (par_charge, UnionOpexFixed)
666674 check_fixed_opex (par_charge, 𝒯ᴵⁿᵛ, check_timeprofiles)
667675 end
668676 @assert_or_log (
669- sum (capacity (par_level, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
677+ all (capacity (par_level, t) ≥ 0 for t ∈ 𝒯),
670678 " The level capacity must be non-negative."
671679 )
672680 if isa (par_level, UnionOpexFixed)
673681 check_fixed_opex (par_level, 𝒯ᴵⁿᵛ, check_timeprofiles)
674682 end
675683 if isa (par_discharge, UnionCapacity)
676684 @assert_or_log (
677- sum (capacity (par_discharge, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
678- " The charge capacity must be non-negative."
685+ all (capacity (par_discharge, t) ≥ 0 for t ∈ 𝒯),
686+ " The discharge capacity must be non-negative."
679687 )
680688 end
681689 if isa (par_discharge, UnionOpexFixed)
682690 check_fixed_opex (par_discharge, 𝒯ᴵⁿᵛ, check_timeprofiles)
683691 end
684- @assert_or_log (
685- sum (inputs (n, p) ≥ 0 for p ∈ inputs (n)) == length ( inputs (n)),
692+ has_input (n) && @assert_or_log (
693+ all (inputs (n, p) ≥ 0 for p ∈ inputs (n)),
686694 " The values for the Dictionary `input` must be non-negative."
687695 )
688- @assert_or_log (
689- sum (outputs (n, p) ≥ 0 for p ∈ outputs (n)) == length ( outputs (n)),
696+ has_output (n) && @assert_or_log (
697+ all (outputs (n, p) ≥ 0 for p ∈ outputs (n)),
690698 " The values for the Dictionary `output` must be non-negative."
691699 )
692700end
693- """
694- check_node(n::Sink, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
695701
696- This method checks that a `Sink` node is valid.
702+ """
703+ check_node_default(n::Sink, 𝒯, modeltype::EnergyModel, check_timeprofiles::Bool)
697704
698- These checks are always performed, if the user is not creating a new method. Hence, it is
699- important that a new `Sink` type includes at least the same fields as in the [`RefSink`](@ref)
700- node or that a new `Source` type receives a new method for `check_node`.
705+ Subroutine that can be utilized in other packages for incorporating the standard tests for
706+ a [`Sink`](@ref) node.
701707
702708## Checks
703709- The field `cap` is required to be non-negative.
704710- The values of the dictionary `input` are required to be non-negative.
705711- The dictionary `penalty` is required to have the keys `:deficit` and `:surplus`.
706712- The sum of the values `:deficit` and `:surplus` in the dictionary `penalty` has to be
707- non-negative to avoid an infeasible model.
713+ non-negative to avoid an infeasible model.
708714"""
709- function check_node (n:: Sink , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
715+ function check_node_default (n:: Sink , 𝒯, modeltype:: EnergyModel , check_timeprofiles:: Bool )
710716 @assert_or_log (
711- sum (capacity (n, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
717+ all (capacity (n, t) ≥ 0 for t ∈ 𝒯),
712718 " The capacity must be non-negative."
713719 )
714720 @assert_or_log (
715- sum (inputs (n, p) ≥ 0 for p ∈ inputs (n)) == length ( inputs (n)),
721+ all (inputs (n, p) ≥ 0 for p ∈ inputs (n)),
716722 " The values for the Dictionary `input` must be non-negative."
717723 )
718724 @assert_or_log (
@@ -723,11 +729,13 @@ function check_node(n::Sink, 𝒯, modeltype::EnergyModel, check_timeprofiles::B
723729 if :surplus ∈ keys (n. penalty) && :deficit ∈ keys (n. penalty)
724730 # The if-condition was checked above.
725731 @assert_or_log (
726- sum (surplus_penalty (n, t) + deficit_penalty (n, t) ≥ 0 for t ∈ 𝒯) == length ( 𝒯),
732+ all (surplus_penalty (n, t) + deficit_penalty (n, t) ≥ 0 for t ∈ 𝒯),
727733 " An inconsistent combination of `:surplus` and `:deficit` leads to an infeasible model."
728734 )
729735 end
730736end
737+
738+
731739"""
732740 check_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles::Bool)
733741
@@ -758,7 +766,7 @@ function check_fixed_opex(n, 𝒯ᴵⁿᵛ, check_timeprofiles::Bool)
758766 # Check that the value is positive in all cases
759767 if bool_sp
760768 @assert_or_log (
761- sum (opex_fixed (n, t_inv) ≥ 0 for t_inv ∈ 𝒯ᴵⁿᵛ) == length ( 𝒯ᴵⁿᵛ),
769+ all (opex_fixed (n, t_inv) ≥ 0 for t_inv ∈ 𝒯ᴵⁿᵛ),
762770 " The fixed OPEX must be non-negative."
763771 )
764772 end
0 commit comments