Example #1
0
        public static List <Cycle> ExtractCycles(List <DataPoint> points)
        {
            Log.Info($"ExtractCycles started for '{points.Count}' points");

            //Cycles can be not in order, so we have to fix it first
            SortedList <int, List <DataPoint> > sortedList = new SortedList <int, List <DataPoint> >();

            foreach (var p in points)
            {
                if (sortedList.ContainsKey(p.CycleIndex))
                {
                    sortedList[p.CycleIndex].Add(p);
                }
                else
                {
                    sortedList.Add(p.CycleIndex, new List <DataPoint> {
                        p
                    });
                }
            }

            List <DataPoint> updatedPointsAfterSorting = new List <DataPoint>();
            List <Cycle>     cycles = new List <Cycle>();
            double?          lastRestVoltageFound = null;

            foreach (KeyValuePair <int, List <DataPoint> > sortedCycleKvp in sortedList)
            {
                var currentPoint = updatedPointsAfterSorting.Count;
                int cycleIndex   = sortedCycleKvp.Key;
                List <DataPoint> cycleDataPoints = sortedCycleKvp.Value.OrderBy(c => c.Time).ToList();
                updatedPointsAfterSorting.AddRange(cycleDataPoints);

                var cycle = new Cycle
                {
                    Index           = cycleIndex,
                    FirstPointIndex = currentPoint,
                    PointCount      = cycleDataPoints.Count
                };

                foreach (DataPoint cyclePoint in cycleDataPoints)
                {
                    if (cycle.Time == null)
                    {
                        //Set first point time
                        cycle.Time = cyclePoint.Time;
                    }

                    if (cyclePoint.Energy != null)
                    {
                        cycle.ChargeEnergy = cyclePoint.Energy;
                    }

                    if (cyclePoint.DischargeEnergy != null)
                    {
                        cycle.DischargeEnergy = cyclePoint.DischargeEnergy;
                    }

                    //Only update if last point is not on the REST step, because it is 0 or useless
                    if (cyclePoint.Current != null && cyclePoint.CycleStep != CycleStep.Rest)
                    {
                        if (cyclePoint.CycleStep == CycleStep.ChargeCC ||
                            cyclePoint.CycleStep == CycleStep.ChargeCV)
                        {
                            cycle.EndCurrent = cyclePoint.Current;
                        }
                        else if (cyclePoint.CycleStep == CycleStep.Discharge)
                        {
                            cycle.DischargeEndCurrent = cyclePoint.Current;
                        }
                    }

                    // find last rest value for a given cycle before charge and discharge
                    if (cyclePoint.CycleStep == CycleStep.Rest)
                    {
                        lastRestVoltageFound = cyclePoint.Voltage.Value;
                    }

                    if (cyclePoint.Voltage != null && cyclePoint.CycleStep != CycleStep.Rest)
                    {
                        if (cyclePoint.CycleStep == CycleStep.ChargeCC ||
                            cyclePoint.CycleStep == CycleStep.ChargeCV)
                        {
                            cycle.EndVoltage = cyclePoint.Voltage;
                            if (cycle.EndRestVoltage == null)
                            {
                                cycle.EndRestVoltage = lastRestVoltageFound;
                            }
                        }
                        else if (cyclePoint.CycleStep == CycleStep.Discharge)
                        {
                            cycle.DischargeEndVoltage = cyclePoint.Voltage;
                            if (cycle.EndRestDischargeVoltage == null)
                            {
                                cycle.EndRestDischargeVoltage = lastRestVoltageFound;
                            }
                        }
                    }
                    if (cyclePoint.Temperature != null && cyclePoint.CycleStep != CycleStep.Rest)
                    {
                        cycle.Temperature = cyclePoint.Temperature;
                    }

                    // find first discharge value for a given cycle
                    if (cyclePoint.CycleStep == CycleStep.Discharge)
                    {
                        if (cycle.StartDischargeVoltage == null &&
                            cycle.StartDischargeCurrent == null)
                        {
                            cycle.StartDischargeCurrent = cyclePoint.Current;
                            cycle.StartDischargeVoltage = cyclePoint.Voltage;
                        }

                        if (cycle.EndRestDischargeVoltage != null &&
                            cycle.StartResistanceDischargeCurrent == null &&
                            cycle.StartResistanceDischargeVoltage == null)
                        {
                            cycle.StartResistanceDischargeCurrent = cyclePoint.Current;
                            cycle.StartResistanceDischargeVoltage = cyclePoint.Voltage;
                        }
                    }

                    // find first charge value for a given cycle
                    if ((cyclePoint.CycleStep == CycleStep.ChargeCC ||
                         cyclePoint.CycleStep == CycleStep.ChargeCV))
                    {
                        if (cycle.StartChargeVoltage == null &&
                            cycle.StartCurrent == null)
                        {
                            cycle.StartCurrent       = cyclePoint.Current;
                            cycle.StartChargeVoltage = cyclePoint.Voltage;
                        }

                        if (cycle.EndRestVoltage != null &&
                            cycle.StartResistanceVoltage == null &&
                            cycle.StartResistanceCurrent == null)
                        {
                            cycle.StartResistanceCurrent = cyclePoint.Current;
                            cycle.StartResistanceVoltage = cyclePoint.Voltage;
                        }
                    }

                    currentPoint++;

                    //Update cycle time on the last step
                    if (currentPoint == cycleDataPoints.Count)
                    {
                        cycle.Time = cyclePoint.Time - cycle.Time;
                    }
                }

                if (cycle.EndRestVoltage == null)
                {
                    cycle.EndRestVoltage = lastRestVoltageFound;
                }

                if (cycle.EndRestDischargeVoltage == null)
                {
                    cycle.EndRestDischargeVoltage = lastRestVoltageFound;
                }

                cycles.Add(cycle);
            }

            double maxChargeCapacity      = double.MinValue;
            int    indexMaxChargeCapacity = int.MinValue;
            double maxDischargeCapacity   = double.MinValue;
            int    indexDischargeCapacity = int.MinValue;

            for (var i = 0; i < cycles.Count; i++)
            {
                var cycle = cycles[i];

                cycle.MidVoltage        = GetMidVoltage(updatedPointsAfterSorting, cycle.FirstPointIndex, cycle.PointCount);
                cycle.ChargeCapacity    = GetChargeCapacity(updatedPointsAfterSorting, cycle.FirstPointIndex, cycle.PointCount);
                cycle.DischargeCapacity = GetDischargeCapacity(updatedPointsAfterSorting, cycle.FirstPointIndex, cycle.PointCount);

                PopulateResistance(cycle, cycles, i);

                if (cycle.ChargeCapacity.HasValue)
                {
                    // Update value first time when we found charge capacity
                    if (Math.Abs(maxChargeCapacity - double.MinValue) < Tolerance)
                    {
                        maxChargeCapacity      = cycle.ChargeCapacity.Value;
                        indexMaxChargeCapacity = i;
                    }
                    // Only pick max value from the first maxCyclesForCalculation cycles.
                    else if (cycle.ChargeCapacity.Value > maxChargeCapacity &&
                             i < MaxStartCyclesForCalculation)
                    {
                        maxChargeCapacity = cycle.ChargeCapacity.Value;
                    }
                }
                if (cycle.DischargeCapacity.HasValue)
                {
                    // Update value first time when we found discharge capacity
                    if (Math.Abs(maxDischargeCapacity - double.MinValue) < Tolerance)
                    {
                        maxDischargeCapacity   = cycle.DischargeCapacity.Value;
                        indexDischargeCapacity = i;
                    }
                    // Only pick max value from the first maxCyclesForCalculation cycles.
                    else if (cycle.DischargeCapacity.Value > maxDischargeCapacity &&
                             i < MaxStartCyclesForCalculation)
                    {
                        maxDischargeCapacity = cycle.DischargeCapacity.Value;
                    }
                }

                cycle.Power          = cycle.EndCurrent * cycle.EndVoltage;
                cycle.DischargePower = cycle.DischargeEndCurrent * cycle.EndVoltage;
            }

            Log.Info($"indexMaxChargeCapacity: '{indexMaxChargeCapacity}', indexDischargeCapacity: '{indexDischargeCapacity}' maxChargeCapacity: '{maxChargeCapacity}', maxDischargeCapacity: '{maxDischargeCapacity}'");

            UpdateCapacityRetention(cycles, indexMaxChargeCapacity, indexDischargeCapacity, maxChargeCapacity, maxDischargeCapacity);

            Log.Info($"ExtractCycles finished '{cycles.Count}' cycles extracted.");

            return(cycles);
        }
Example #2
0
File: Plotter.cs Project: dqdv/DqDv
 private static IEnumerable <Point2Y> Plot2Y(List <DataPoint> points, bool is2Y, Cycle cycle, Func <DataPoint, double?> getX, Func <DataPoint, double?[]> getY, Parameters parameters, Func <DataPoint, bool> filter = null)
 {
     return(ApplyYFilter(Plot2Y(points, is2Y, cycle.FirstPointIndex, cycle.PointCount, getX, getY, filter).ToList(), parameters, is2Y));
 }
Example #3
0
        private static void PopulateResistance(Cycle cycle, List <Cycle> cycles, int i)
        {
            //check for division on zero
            if (cycle.StartResistanceCurrent != null)
            {
                if (cycle.StartCurrent != 0)
                {
                    double?chargeResistance = (cycle.StartResistanceVoltage - cycle.EndRestVoltage) / cycle.StartResistanceCurrent;
                    if (chargeResistance != null)
                    {
                        //Resistance is only positive, so we need to take absolute value
                        //Resistance is calculated in Ohms so we have to multiply by 1000
                        cycle.ResistanceOhms = Math.Abs(chargeResistance.Value) * 1000;
                    }
                }
                else
                {
                    cycles[i].ResistanceOhms = 0;
                }
            }
            else
            {
                //pick values from the next cycle if it exists
                if (i > 0 && i < cycles.Count)
                {
                    Cycle previousCycle = cycles[i - 1];
                    if (previousCycle != null &&
                        previousCycle.ResistanceOhms == null &&
                        cycle.StartResistanceCurrent != null &&
                        cycle.StartResistanceCurrent != 0 &&
                        previousCycle.EndRestVoltage != null)
                    {
                        double?chargeResistance = (cycle.StartResistanceVoltage - previousCycle.EndRestVoltage) / cycle.StartResistanceCurrent;
                        previousCycle.ResistanceOhms = Math.Abs(chargeResistance.Value) * 1000;
                    }
                }
            }

            //check for division on zero
            if (cycle.StartResistanceDischargeCurrent != null)
            {
                if (cycle.StartResistanceDischargeCurrent != 0)
                {
                    double?dischargeResistance = (cycle.StartResistanceDischargeVoltage - cycle.EndRestDischargeVoltage) / cycle.StartResistanceDischargeCurrent;
                    if (dischargeResistance != null)
                    {
                        //Resistance is only positive, so we need to take absolute value
                        //Resistance is calculated in Ohms so we have to multiply by 1000
                        cycle.DischargeResistance = Math.Abs(dischargeResistance.Value) * 1000;
                    }
                }
                else
                {
                    cycle.DischargeResistance = 0;
                }
            }
            else
            {
                //pick values from the next cycle if it exists
                if (i > 0 && i < cycles.Count)
                {
                    Cycle previousCycle = cycles[i - 1];
                    if (previousCycle != null &&
                        previousCycle.DischargeResistance == null &&
                        cycle.StartResistanceDischargeCurrent != null &&
                        cycle.StartResistanceDischargeCurrent != 0 &&
                        previousCycle.EndRestVoltage != null)
                    {
                        double?dischargeResistance = (cycle.StartResistanceDischargeVoltage - previousCycle.EndRestVoltage) / cycle.StartResistanceDischargeCurrent;
                        previousCycle.DischargeResistance = Math.Abs(dischargeResistance.Value) * 1000;
                    }
                }
            }
        }