public void Add(Entity entity, Simulation simulation, string parameterName, string expression, bool beforeTemperature, bool beforeLoad)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            if (parameterName == null)
            {
                throw new ArgumentNullException(nameof(parameterName));
            }

            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            if (!SimulationSpecificUpdates.ContainsKey(simulation))
            {
                SimulationSpecificUpdates[simulation] = new Dictionary <Entity, EntityUpdate>();
            }

            if (!SimulationSpecificUpdates[simulation].ContainsKey(entity))
            {
                SimulationSpecificUpdates[simulation][entity] = new EntityUpdate();
            }

            if (beforeLoad)
            {
                SimulationSpecificUpdates[simulation][entity].ParameterUpdatesBeforeLoad.Add(
                    new EntityParameterExpressionValueUpdate()
                {
                    ParameterName = parameterName,
                    Expression    = new DynamicExpression(expression),
                });
            }

            if (beforeTemperature)
            {
                SimulationSpecificUpdates[simulation][entity].ParameterUpdatesBeforeTemperature.Add(new EntityParameterExpressionValueUpdate()
                {
                    Expression    = new DynamicExpression(expression),
                    ParameterName = parameterName,
                });
            }
        }
        public void Add(IEntity entity, Simulation simulation, string parameterName, double value, bool beforeTemperature, bool beforeLoad)
        {
            if (entity == null)
            {
                throw new ArgumentNullException(nameof(entity));
            }

            if (simulation == null)
            {
                throw new ArgumentNullException(nameof(simulation));
            }

            if (parameterName == null)
            {
                throw new ArgumentNullException(nameof(parameterName));
            }

            if (!SimulationSpecificUpdates.ContainsKey(simulation))
            {
                SimulationSpecificUpdates[simulation] = new Dictionary <IEntity, EntityUpdate>();
            }

            if (!SimulationSpecificUpdates[simulation].ContainsKey(entity))
            {
                SimulationSpecificUpdates[simulation][entity] = new EntityUpdate();
            }

            if (beforeLoad)
            {
                SimulationSpecificUpdates[simulation][entity].ParameterUpdatesBeforeLoad.Add(new EntityParameterDoubleValueUpdate {
                    ParameterName = parameterName, Value = value
                });
            }

            if (beforeTemperature)
            {
                SimulationSpecificUpdates[simulation][entity].ParameterUpdatesBeforeTemperature.Add(new EntityParameterDoubleValueUpdate {
                    ParameterName = parameterName, Value = value
                });
            }
        }
        public void Apply(BaseSimulation simulation)
        {
            if (simulation == null)
            {
                throw new ArgumentNullException(nameof(simulation));
            }

            simulation.BeforeLoad += (sender, args) =>
            {
                foreach (var entity in CommonUpdates.Keys)
                {
                    var beforeLoads = CommonUpdates[entity].ParameterUpdatesBeforeLoad;

                    foreach (var entityUpdate in beforeLoads)
                    {
                        var parameter = GetEntitySimulationParameter(entityUpdate.ParameterName, entity, simulation, StringComparerProvider.Get(IsParameterNameCaseSensitive));

                        if (parameter != null)
                        {
                            Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entity);

                            var value = entityUpdate.GetValue(context);

                            if (!double.IsNaN(value))
                            {
                                parameter.Value = value;
                            }
                        }
                    }
                }

                if (SimulationSpecificUpdates.ContainsKey(simulation))
                {
                    foreach (var entityPair in SimulationSpecificUpdates[simulation])
                    {
                        var beforeLoads = entityPair.Value.ParameterUpdatesBeforeLoad;

                        foreach (var entityUpdate in beforeLoads)
                        {
                            var parameter = GetEntitySimulationParameter(entityUpdate.ParameterName, entityPair.Key, simulation, StringComparerProvider.Get(IsParameterNameCaseSensitive));

                            if (parameter != null)
                            {
                                Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entityPair.Key);

                                var value = entityUpdate.GetValue(context);
                                if (!double.IsNaN(value))
                                {
                                    parameter.Value = value;
                                }
                            }
                        }
                    }
                }
            };

            simulation.BeforeTemperature += (sender, args) =>
            {
                foreach (var entity in CommonUpdates.Keys)
                {
                    var beforeTemperature = CommonUpdates[entity].ParameterUpdatesBeforeTemperature;

                    foreach (var entityUpdate in beforeTemperature)
                    {
                        var parameter = GetEntitySimulationParameter(entityUpdate.ParameterName, entity, simulation, StringComparerProvider.Get(IsParameterNameCaseSensitive));

                        if (parameter != null)
                        {
                            Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entity);
                            var value = entityUpdate.GetValue(context);

                            if (!double.IsNaN(value))
                            {
                                parameter.Value = value;
                            }
                        }
                    }
                }

                if (SimulationSpecificUpdates.ContainsKey(simulation))
                {
                    foreach (var entityPair in SimulationSpecificUpdates[simulation])
                    {
                        var beforeTemperature = entityPair.Value.ParameterUpdatesBeforeTemperature;

                        foreach (var entityUpdate in beforeTemperature)
                        {
                            var parameter = GetEntitySimulationParameter(entityUpdate.ParameterName, entityPair.Key, simulation, StringComparerProvider.Get(IsParameterNameCaseSensitive));

                            if (parameter != null)
                            {
                                Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entityPair.Key);

                                var value = entityUpdate.GetValue(context);
                                if (!double.IsNaN(value))
                                {
                                    parameter.Value = value;
                                }
                            }
                        }
                    }
                }
            };
        }
        public void Apply(Simulation simulation)
        {
            if (simulation == null)
            {
                throw new ArgumentNullException(nameof(simulation));
            }

            if (simulation is BiasingSimulation biasingSimulation)
            {
                biasingSimulation.BeforeLoad += (sender, args) =>
                {
                    foreach (var entity in CommonUpdates.Keys)
                    {
                        var beforeLoads = CommonUpdates[entity].ParameterUpdatesBeforeLoad;

                        foreach (var entityUpdate in beforeLoads)
                        {
                            Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entity);

                            var value = entityUpdate.GetValue(context);
                            if (!double.IsNaN(value))
                            {
                                entity.CreateParameterSetter <double>(entityUpdate.ParameterName)?.Invoke(value);
                            }
                        }
                    }

                    if (SimulationSpecificUpdates.ContainsKey(simulation))
                    {
                        foreach (var entityPair in SimulationSpecificUpdates[simulation])
                        {
                            var beforeLoads = entityPair.Value.ParameterUpdatesBeforeLoad;

                            foreach (var entityUpdate in beforeLoads)
                            {
                                Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entityPair.Key);

                                var value = entityUpdate.GetValue(context);
                                if (!double.IsNaN(value))
                                {
                                    entityPair.Key.CreateParameterSetter <double>(entityUpdate.ParameterName)?.Invoke(value);
                                }
                            }
                        }
                    }
                };

                biasingSimulation.BeforeTemperature += (sender, args) =>
                {
                    foreach (var entity in CommonUpdates.Keys)
                    {
                        var beforeTemperature = CommonUpdates[entity].ParameterUpdatesBeforeTemperature;

                        foreach (var entityUpdate in beforeTemperature)
                        {
                            Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entity);

                            var value = entityUpdate.GetValue(context);
                            if (!double.IsNaN(value))
                            {
                                entity.CreateParameterSetter <double>(entityUpdate.ParameterName)?.Invoke(value);
                            }
                        }
                    }

                    if (SimulationSpecificUpdates.ContainsKey(simulation))
                    {
                        foreach (var entityPair in SimulationSpecificUpdates[simulation])
                        {
                            var beforeTemperature = entityPair.Value.ParameterUpdatesBeforeTemperature;

                            foreach (var entityUpdate in beforeTemperature)
                            {
                                Common.Evaluation.EvaluationContext context = GetEntityContext(simulation, entityPair.Key);

                                var value = entityUpdate.GetValue(context);
                                if (!double.IsNaN(value))
                                {
                                    entityPair.Key.CreateParameterSetter <double>(entityUpdate.ParameterName)?.Invoke(value);
                                }
                            }
                        }
                    }
                };
            }
        }