private SteadyStateModel GetSteadyStateModel(
            List <ElementNode> elements,
            List <ConnectionNode> rootConnections,
            Object modelParameters)
        {
            Dictionary <string, ElementEntry> elementEntries = new Dictionary <string, ElementEntry>();
            int nodeIndicies       = 0;
            SteadyStateModel model = new SteadyStateModel();

            foreach (var element in elements)
            {
                //get Object from element.Definition
                Object obj = BuildObject(element.Definition);

                //get Element description( nodes and parameters)
                if (!elementsMap.ContainsKey(obj.Name))
                {
                    errors.Add(new ErrorMessage($"Не существует элемента {obj.Name}", element.Line, element.Position));
                    continue;
                }
                ElementDescription description = elementsMap[obj.Name];

                Dictionary <string, Pin> elementPins = new Dictionary <string, Pin>();
                var keys = description.GetNodes();
                for (int i = 0; i < keys.Count; i++)
                {
                    string key = keys.ElementAt(i);
                    Pin    pin = description.CreatePin(key, nodeIndicies);
                    elementPins.Add(key, pin);
                    model.AddPin(pin);
                    nodeIndicies++;
                }
                //create element entry
                elementEntries.Add(element.Id, new ElementEntry(description, obj, elementPins));
                bool valid = description.Validate(ref obj, ref errors);
                if (valid)
                {
                    try
                    {
                        if (description.Validate(ref obj, ref errors))
                        {
                            ISteadyStateElement modelElement = description.CreateSteadyStateElement(obj, elementPins);
                            if (modelElement is null)
                            {
                                errors.Add(new ErrorMessage($"Element {obj.Name} cannot be used in steady state model", element.Line, element.Position));
                            }
                            else
                            {
                                model.AddElement(modelElement);
                            }
                        }
                    }
                    catch (MissingValueException exc)
                    {
                        errors.Add(new ErrorMessage($"Missing parameter {exc.Key} in element {obj.Name}", element.Line, element.Position));
                    }
                    catch (Exception exc)
                    {
                        errors.Add(new ErrorMessage($"Ошибка при создании элемента {obj.Name}: {exc.Message}", element.Line, element.Position));
                    }
                }
            }
            //resolve connections between elements
            List <Connection> connections = new List <Connection>();

            foreach (var connection in rootConnections)
            {
                try
                {
                    if (!elementEntries.ContainsKey(connection.Element1))
                    {
                        errors.Add(new ErrorMessage($"Non existing element {connection.Element1} in connection", connection.Line, connection.Position));
                        continue;
                    }
                    if (!elementEntries.ContainsKey(connection.Element2))
                    {
                        errors.Add(new ErrorMessage($"Non existing element {connection.Element2} in connection", connection.Line, connection.Position));
                        continue;
                    }
                    ElementEntry       entry1   = elementEntries[connection.Element1];
                    ElementEntry       entry2   = elementEntries[connection.Element2];
                    ElementDescription element1 = entry1.GetDescription();
                    ElementDescription element2 = entry2.GetDescription();
                    if (!element1.ContainsNode(connection.Node1))
                    {
                        errors.Add(new ErrorMessage($"Non existing pin {connection.Node1} in element {connection.Element1}", connection.Line, connection.Position));
                        continue;
                    }
                    if (!element2.ContainsNode(connection.Node2))
                    {
                        errors.Add(new ErrorMessage($"Non existing element {connection.Node2} in element {connection.Element2}", connection.Line, connection.Position));
                        continue;
                    }
                    ElementDescription.NodeType node1 = element1.GetNodeType(connection.Node1);
                    ElementDescription.NodeType node2 = element2.GetNodeType(connection.Node2);
                    if (node1 != node2)
                    {
                        errors.Add(new ErrorMessage($"Pins in connection ({connection.Element1}.{connection.Node1},{connection.Element2}.{connection.Node2}) have different types", connection.Line, connection.Position));
                        continue;
                    }
                    connections.Add(new Connection(entry1.GetPin(connection.Node1), entry2.GetPin(connection.Node2)));
                }
                catch (Exception exc)
                {
                    throw exc;
                }
            }
            foreach (Connection connection in connections)
            {
                model.AddElement(connection.CreateSteadyStateElement());
            }
            try
            {
                Object solver = (Object)Convert(modelParameters.GetValue("solver"), Constant.Type.Object);
                switch (solver.Name)
                {
                case "newton":
                    FloatValue fAbsTol    = Convert(solver.GetValue("fAbsTol"), Constant.Type.Float) as FloatValue;
                    IntValue   iterations = Convert(solver.GetValue("iterations"), Constant.Type.Int) as IntValue;
                    FloatValue alpha      = Convert(solver.GetValue("alpha"), Constant.Type.Float) as FloatValue;
                    model.SetSolver(new SteadyStateNewtonSolver(fAbsTol.Value, iterations.Value, alpha.Value));
                    break;

                default:
                    errors.Add(new ErrorMessage("Unknown solver in steadystate model"));
                    return(null);
                }
                FloatValue baseFrequency = (FloatValue)Convert(modelParameters.GetValue("baseFrequency"), Constant.Type.Float);
                model.SetBaseFrequency(baseFrequency.Value);
            }
            catch (MissingValueException exc)
            {
                errors.Add(new ErrorMessage($"Отсутствует аргумент {exc.Key} в определении модели."));
                return(null);
            }
            catch (Exception exc)
            {
                errors.Add(new ErrorMessage($"Exception: {exc.Message}"));
                return(null);
            }
            return(model);
        }
 public Connection(Pin pin1, Pin pin2)
 {
     this.pin1 = pin1;
     this.pin2 = pin2;
 }
        private Transient.TransientModel GetTransientModel(
            List <ElementNode> elements,
            List <ConnectionNode> rootConnections,
            Object modelParameters)
        {
            Dictionary <string, ElementEntry> elementEntries = new Dictionary <string, ElementEntry>();
            int nodeIndicies = 0;

            Transient.TransientModel model = new Transient.TransientModel();
            foreach (var element in elements)
            {
                //get Object from element.Definition
                Object obj = BuildObject(element.Definition);

                if (!elementsMap.ContainsKey(obj.Name))
                {
                    errors.Add(new ErrorMessage($"Не существует элемента {obj.Name}", element.Line, element.Position));
                    continue;
                }
                //get Element description( nodes and parameters)
                ElementDescription description = elementsMap[obj.Name];

                Dictionary <string, Pin> elementPins = new Dictionary <string, Pin>();
                var keys = description.GetNodes();
                for (int i = 0; i < keys.Count; i++)
                {
                    string key = keys.ElementAt(i);
                    Pin    pin = description.CreatePin(key, nodeIndicies);
                    elementPins.Add(key, pin);
                    model.AddPin(pin);
                    nodeIndicies++;
                }
                //create element entry
                elementEntries.Add(element.Id, new ElementEntry(description, obj, elementPins));
                bool valid = description.Validate(ref obj, ref errors);
                if (valid)
                {
                    try
                    {
                        if (description.Validate(ref obj, ref errors))
                        {
                            ITransientElement modelElement = description.CreateTransientElement(obj, elementPins);
                            if (modelElement is null)
                            {
                                errors.Add(new ErrorMessage($"Элемент {obj.Name} не может использоваться для расчёта переходных процессов", element.Line, element.Position));
                            }
                            else
                            {
                                model.AddElement(modelElement);
                            }
                        }
                    }
                    catch (MissingValueException exc)
                    {
                        errors.Add(new ErrorMessage($"Отсутствует параметр {exc.Key} в элементе {obj.Name}", element.Line, element.Position));
                    }
                    catch (Exception)
                    {
                        errors.Add(new ErrorMessage($"Ошибка при создании элемента {obj.Name}", element.Line, element.Position));
                    }
                }
            }
            //resolve connections between elements
            List <Connection> connections = new List <Connection>();

            foreach (var connection in rootConnections)
            {
                try
                {
                    if (!elementEntries.ContainsKey(connection.Element1))
                    {
                        errors.Add(new ErrorMessage($"Non existing element {connection.Element1} in connection", connection.Line, connection.Position));
                        continue;
                    }
                    if (!elementEntries.ContainsKey(connection.Element2))
                    {
                        errors.Add(new ErrorMessage($"Non existing element {connection.Element2} in connection", connection.Line, connection.Position));
                        continue;
                    }
                    ElementEntry       entry1   = elementEntries[connection.Element1];
                    ElementEntry       entry2   = elementEntries[connection.Element2];
                    ElementDescription element1 = entry1.GetDescription();
                    ElementDescription element2 = entry2.GetDescription();
                    if (!element1.ContainsNode(connection.Node1))
                    {
                        errors.Add(new ErrorMessage($"Non existing pin {connection.Node1} in element {connection.Element1}", connection.Line, connection.Position));
                        continue;
                    }
                    if (!element2.ContainsNode(connection.Node2))
                    {
                        errors.Add(new ErrorMessage($"Non existing element {connection.Node2} in element {connection.Element2}", connection.Line, connection.Position));
                        continue;
                    }
                    ElementDescription.NodeType node1 = element1.GetNodeType(connection.Node1);
                    ElementDescription.NodeType node2 = element2.GetNodeType(connection.Node2);
                    if (node1 != node2)
                    {
                        errors.Add(new ErrorMessage($"Pins in connection ({connection.Element1}.{connection.Node1},{connection.Element2}.{connection.Node2}) have different types", connection.Line, connection.Position));
                        continue;
                    }
                    connections.Add(new Connection(entry1.GetPin(connection.Node1), entry2.GetPin(connection.Node2)));
                }
                catch (Exception exc)
                {
                    throw exc;
                }
            }
            foreach (Connection connection in connections)
            {
                model.AddElement(connection.CreateTransientElement());
            }
            try
            {
                Object solver = (Object)Convert(modelParameters.GetValue("solver"), Constant.Type.Object);
                switch (solver.Name)
                {
                case "radauIIA5":
                {
                    FloatValue fAbsTol    = Convert(solver.GetValue("fAbsTol"), Constant.Type.Float) as FloatValue;
                    IntValue   iterations = Convert(solver.GetValue("iterations"), Constant.Type.Int) as IntValue;
                    FloatValue alpha      = Convert(solver.GetValue("alpha"), Constant.Type.Float) as FloatValue;
                    FloatValue step       = Convert(solver.GetValue("step"), Constant.Type.Float) as FloatValue;
                    model.SetSolver(new Equations.DAE.Implicit.RADAUIIA5(fAbsTol.Value, iterations.Value, alpha.Value, step.Value));
                }
                break;

                case "radauIIA3":
                {
                    FloatValue fAbsTol    = Convert(solver.GetValue("fAbsTol"), Constant.Type.Float) as FloatValue;
                    IntValue   iterations = Convert(solver.GetValue("iterations"), Constant.Type.Int) as IntValue;
                    FloatValue alpha      = Convert(solver.GetValue("alpha"), Constant.Type.Float) as FloatValue;
                    FloatValue step       = Convert(solver.GetValue("step"), Constant.Type.Float) as FloatValue;
                    model.SetSolver(new Equations.DAE.Implicit.RADAUIIA3(fAbsTol.Value, iterations.Value, alpha.Value, step.Value));
                }
                break;

                case "bdf1":
                {
                    FloatValue fAbsTol    = Convert(solver.GetValue("fAbsTol"), Constant.Type.Float) as FloatValue;
                    IntValue   iterations = Convert(solver.GetValue("iterations"), Constant.Type.Int) as IntValue;
                    FloatValue alpha      = Convert(solver.GetValue("alpha"), Constant.Type.Float) as FloatValue;
                    FloatValue step       = Convert(solver.GetValue("step"), Constant.Type.Float) as FloatValue;
                    model.SetSolver(new Equations.DAE.Implicit.BDF1(fAbsTol.Value, iterations.Value, alpha.Value, step.Value));
                }
                break;

                default:
                    errors.Add(new ErrorMessage("Unknown solver in transient model"));
                    return(null);
                }
                FloatValue t0 = Convert(modelParameters.GetValue("t0"), Constant.Type.Float) as FloatValue;
                FloatValue t1 = Convert(modelParameters.GetValue("t1"), Constant.Type.Float) as FloatValue;
                model.SetT0(t0.Value);
                model.SetT1(t1.Value);
            }
            catch (MissingValueException exc)
            {
                errors.Add(new ErrorMessage($"Отсутствует аргумент {exc.Key} в определении модели."));
                return(null);
            }
            catch (Exception exc)
            {
                errors.Add(new ErrorMessage($"Exception: {exc.Message}"));
                return(null);
            }
            return(model);
        }