internal RearrangedControlEquation(EquationArgument subject, List <EquationArgument> arguments,
                                    List <Constant> constants, Func <List <EquationArgument>, List <Constant>, double> calcSubjectValue, ControlEquation parentControlEquation)
 {
     _arguments            = arguments;
     _constants            = constants;
     Subject               = subject;
     _calcSubjectValue     = calcSubjectValue;
     ParentControlEquation = parentControlEquation;
 }
        public override RearrangedControlEquation GetRearrangedEquation(EquationArgument subject)
        {
            if (subject == null)
            {
                throw new ArgumentException("Subject cannot be equal to null");
            }

            var matches   = 0;
            var arguments = new List <EquationArgument>();

            foreach (var argument in _arguments)
            {
                if (argument == subject)
                {
                    matches++;
                    continue;
                }

                arguments.Add(argument);
            }

            if (matches != 1)
            {
                throw new ArgumentException("The argument that is supposed to be the subject wasn't found among ControlEquation arguments");
            }


            double calcSubjectValue(List <EquationArgument> equationArguments, List <Constant> equationConstants)
            {
                double subjectValue = 0.0;

                foreach (var argument in equationArguments)
                {
                    subjectValue -= argument.Value;
                }
                return(subjectValue);
            };

            return(new RearrangedControlEquation(subject, arguments, null, calcSubjectValue, this));
        }
        public override RearrangedControlEquation GetRearrangedEquation(EquationArgument subject)
        {
            if (subject == null)
            {
                throw new ArgumentException("Subject cannot be equal to null");
            }

            if (subject == Ui)
            {
                double calcSubjectValue(List <EquationArgument> equationArguments, List <Constant> equationConstants)
                {
                    var Pij = equationArguments[0].Value;
                    var Qij = equationArguments[1].Value;
                    var Pji = equationArguments[2].Value;

                    var R = equationConstants[0].Value;

                    var pijPlusPji = Pij + Pji;

                    if (IsCloseToZero(pijPlusPji, NearZeroMarginPowerFlow))
                    {
                        return(double.NaN);
                    }

                    var res = Math.Sqrt(R * (Math.Pow(Pij, 2) + Math.Pow(Qij, 2)) / (pijPlusPji));

                    return(res);
                }

                var arguments = new List <EquationArgument>()
                {
                    Pij, Qij, Pji
                };
                var constants = new List <Constant>()
                {
                    R
                };
                return(new RearrangedControlEquation(subject, arguments, constants, calcSubjectValue, this));
            }

            if (subject == Pij)
            {
                double calcSubjectValue(List <EquationArgument> equationArguments, List <Constant> equationConstants)
                {
                    var Ui  = equationArguments[0].Value;
                    var Qij = equationArguments[1].Value;
                    var Pji = equationArguments[2].Value;

                    var R = equationConstants[0].Value;

                    if (IsCloseToZero(Ui, NearZeroMarginVoltage))
                    {
                        return(double.NaN);
                    }

                    var D = 1 - 4 * R * (R * Math.Pow(Qij, 2) / Math.Pow(Ui, 2) - Pji) / Math.Pow(Ui, 2);

                    if (D <= 0)
                    {
                        return(double.NaN);        // D should be bigger that a=1
                    }
                    var result = (1 - Math.Sqrt(D)) / (2 * R / Math.Pow(Ui, 2));

                    return(result);
                }

                var arguments = new List <EquationArgument>()
                {
                    Ui, Qij, Pji
                };
                var constants = new List <Constant>()
                {
                    R
                };
                return(new RearrangedControlEquation(subject, arguments, constants, calcSubjectValue, this));
            }

            if (subject == Pji)
            {
                double calcSubjectValue(List <EquationArgument> equationArguments, List <Constant> equationConstants)
                {
                    var Ui  = equationArguments[0].Value;
                    var Qij = equationArguments[1].Value;
                    var Pij = equationArguments[2].Value;

                    var R = equationConstants[0].Value;

                    if (IsCloseToZero(Ui, NearZeroMarginVoltage))
                    {
                        return(double.NaN);
                    }

                    var res = R * (Math.Pow(Pij, 2) + Math.Pow(Qij, 2)) / Math.Pow(Ui, 2) - Pij;

                    return(res);
                }

                var arguments = new List <EquationArgument>()
                {
                    Ui, Qij, Pij
                };
                var constants = new List <Constant>()
                {
                    R
                };
                return(new RearrangedControlEquation(subject, arguments, constants, calcSubjectValue, this));
            }

            if (subject == Qij)
            {
                double calcSubjectValue(List <EquationArgument> equationArguments, List <Constant> equationConstants)
                {
                    var Pij = equationArguments[0].Value;
                    var Ui  = equationArguments[1].Value;
                    var Pji = equationArguments[2].Value;

                    var R = equationConstants[0].Value;

                    var pijPlusPji = Pij + Pji;

                    var res = Math.Sqrt(pijPlusPji * Math.Pow(Ui, 2) / R - Math.Pow(Pij, 2));

                    return(res);
                }

                var arguments = new List <EquationArgument>()
                {
                    Pij, Ui, Pji
                };
                var constants = new List <Constant>()
                {
                    R
                };
                return(new RearrangedControlEquation(subject, arguments, constants, calcSubjectValue, this));
            }

            throw new ArgumentException("The argument that is supposed to be the subject wasn't found among ControlEquation arguments");
        }
 protected void AddToArguments(EquationArgument argument)
 {
     argument.AddReferenceToControlEquation(this);
     _arguments.Add(argument);
 }
 public abstract RearrangedControlEquation GetRearrangedEquation(EquationArgument subject);