Concrete formula algorithm

  • 混凝土配料介绍

混凝土施工配合比必须通过实验,满足设计技术指标和施工要求,并经审批后方可使用。混凝土施工配料必须经审核后签发,并严格按签发的混凝土施工配料单进行配料,严禁擅自更改。在施工配料中一旦出现漏配、少配或者错配,混凝土将不允许进仓。

无论采用哪种拌制混凝土的方式,都必须控制好混凝土拌制的质量。首先,要严格按照配料单进行配料,水泥、骨料、水以及掺和料、外加剂等的称量要准确,偏差不超过规定值;其次要将混凝土各组分拌和均匀,遵守规定的投料程序和拌和时间。

  • 参与混凝土混合的元素

    • 水、冰
    • 水泥
    • 小石头
    • 中石头
    • 大石头
    • 特大石头
    • 外加剂等

根据配合比的预先定义,每项元素都有指定的理论用量;但在实际情况下,由于供货的实际规格差异,每种元素的含水率可能存在偏差;而且更为重要的是,4种石头:小石、中石、大石和特大石存在超径和逊径的情形,实际的规格会略有差异,在这种情况下。

  • 石头的规格定义

    • 小石(5~20mm)
    • 中石(20~40mm)
    • 大石(40~80mm)
    • 特大石(80~150mm)
  • 配料算法原理

配料单的算法原理实际上是根据骨料的理论用量对实际用量的求解过程,并依据计算结果,对其他元素用量做调整。

  • 超径和逊径的情形下每种类别的骨料的实际含量

表格 1 – 参考超径和逊径后石头的重量明细

类别 实际用量 超径率 逊径率 砂子 小石 中石 大石
小石 X1 U1 L1 X1*(1-U1) X2*L2
中石 X2 U2 L2 X1*U1 X2*(1-U2-L2) X3*L3
大石 X3 U3 L3 X2*U2 X3*(1-U3-L3) X4*L4
特大石 X4 U4 L4 X3*U3 X4*(1-L4)
  • 含水量

含水率是指元素中水的重量占比:

对于骨料而言,含水率可能为负数,表示吸水;

对于外加剂而言,实际指标是浓度,为了统一公式说明,这里用含水率来做说明(外加剂的含水率=1-浓度);

对于水泥、煤灰,没有含水率

下表列出了各项元素的理论用量和含水量之间的关系:

表格 2 – 各配料的计算公式

类别 理论用量 含水率 含水量
小石 A= X1*(1-U1)+X2*L2 R1 X1*R1
中石 B= X1*U1+X2*(1-U2-L2)+X3*L3 R2 X2*R2
大石 C= X2*U2+X3*(1-U3-L3)+X4*L4 R3 X3*R3
特大石 D= X3*U3+X4*(1-L4) R4 X4*R4
E= X5*(1 – R5) R5 X5*R5
减水剂 F= X6*(1 – R6) R6 X6*R6
引气剂 G= X7*(1 – R7) R7 X7*R7
其他外加剂 H= X8*(1 – R8) R8 X8*R8
  • 水、冰的实际用量调整

因为在配料时其他元素的含水情况,水、冰的实际用量将在理论用量的基础上减去整体含水量,即:实际用量 = 理论用量 – ∑(Xi * Ri)

  • 算法组件MathNet.Numerics介绍

为了简化算法的实现,我们使用了现有的数学组件来求解上述方程组。

MathNet.Numerics是一个基于.NET的数学计算库,其中它提供了一个线性算法可以对上述公式中X1、X2……X5的求解,也就是可以根据相关的参数如:理论用量、含水率和超逊径率计算出各种石头的实际用量。

该算法通过两个矩阵作为输入,一个矩阵是未知数的系数,另一个矩阵是结果(在这里也就是骨料的理论用量),有了这两个矩阵就可以求解出骨料的实际用量。

public class ConcreteMatierial
{
    public string Name { get; set; }
    public double LowerPercent { get; set; }
    public double UpperPercent { get; set; }
    public double TheoreticalAmount { get; set; }
    public double RealAmount { get; set; }
    public double WaterRate { get; set; }
    public double WaterAmount { get; set; }
    public override string ToString()
    {
        return $"{Name}, 逊径:{LowerPercent:0.00%}, 超径:{UpperPercent:0.00%}, 理论用量:{TheoreticalAmount}, 实际用量:{RealAmount:0.00}, 含水率:{WaterRate:0.00%}, 水重:{WaterAmount:0.00}";
    }
}
public class ConcreteFormula
{
    public static void Calc(List<ConcreteMatierial> stones)
    {
        if (stones.Count < 2) throw new ArgumentException();
        var factorTable = new List<double[]>();
        var amounts = new List<double>();

        for (int i = 0; i < stones.Count; i++) {
            double[] factors = new double[stones.Count];
            if (i == 0) {
                factors[0] = 1 - stones[i].UpperPercent;
                factors[1] = stones[i + 1].LowerPercent;
            }
            else if (i == stones.Count - 1) {
                factors[i - 1] = stones[i - 1].UpperPercent;
                factors[i] = 1 - stones[i].LowerPercent;
            }
            else {
                factors[i] = 1 - stones[i].UpperPercent - stones[i].LowerPercent;
                factors[i - 1] = stones[i - 1].UpperPercent;
                factors[i + 1] = stones[i + 1].LowerPercent;
            }
            factorTable.Add(factors);
            amounts.Add(stones[i].TheoreticalAmount);
        }

        var vector = new MathNet.Numerics.LinearAlgebra.Double.DenseVector(amounts.ToArray());
        var matrix = MathNet.Numerics.LinearAlgebra.Double.DenseMatrix.OfRowArrays(factorTable);
        var result = matrix.QR().Solve(vector);

        for (int i = 0; i < stones.Count; i++) {
            stones[i].RealAmount = result.Storage[i];
            if (stones[i].WaterRate == 1) {
                stones[i].WaterAmount = stones[i].RealAmount;
                stones[i].RealAmount = 0;
            }
            else {
                stones[i].RealAmount /= (1 - stones[i].WaterRate);
                stones[i].WaterAmount = stones[i].RealAmount * stones[i].WaterRate;
            }
        }
    }
}
class Program
{
    static void Main(string[] args)
    {
        var stones = new List<ConcreteMatierial>();
        stones.Add(new ConcreteMatierial() { Name = "小石头", TheoreticalAmount = 439, LowerPercent = 0.00, UpperPercent = 0.09, WaterRate = 0.09, });
        stones.Add(new ConcreteMatierial() { Name = "中石头", TheoreticalAmount = 585, LowerPercent = 0.02, UpperPercent = 0.09, WaterRate = 0.04, });
        stones.Add(new ConcreteMatierial() { Name = "大石头", TheoreticalAmount = 439, LowerPercent = 0.41, UpperPercent = 0.00, WaterRate = 0.01, });
        stones.Add(new ConcreteMatierial() { Name = "特大石头", TheoreticalAmount = 0, LowerPercent = 0.09, UpperPercent = 0.00, WaterRate = 0.07, });
        ConcreteFormula.Calc(stones);
        foreach (var stone in stones) {
            Console.WriteLine(stone);
        }
    }
}
  • 程序输出
小石头, 逊径:0.00%, 超径:9.00%, 理论用量:439, 实际用量:523.21, 含水率:9.00%, 水重:47.09
中石头, 逊径:2.00%, 超径:9.00%, 理论用量:585, 实际用量:298.46, 含水率:4.00%, 水重:11.94
大石头, 逊径:41.00%, 超径:0.00%, 理论用量:439, 实际用量:707.44, 含水率:1.00%, 水重:7.07
特大石头, 逊径:9.00%, 超径:0.00%, 理论用量:0, 实际用量:0.00, 含水率:7.00%, 水重:0.00