# Модель расчетов

Расчет профиля и навески разбит на несколько этапов

1. Оптимизация профиля по ионному балансу.
   Профиль оптимизируется по сере и хлору
2. Перерасчет профиля по требуемому EC 
3. Перерасчет профиля по коэфициентам
4. Расчет навески удобрений

# Расчет EC

## Формула Зоневельда

Выполняется при условии того что ионный баланс равен нулю

$$ \left(
\frac{m_{NH_4}}{M_N} +
     \frac{2  m_{Ca}}{M_{Ca}} + 
     \frac{2  m_{Mg}}{M_{Mg}} +
     \frac{m_{K}}{M_{K}} 
\right)
     - 
     \left(
     \frac{m_{NO_3}}{M_N} + 
     \frac{m_{P}}{M_{P}} +
     \frac{2m_{S}}{M_{S}} + 
     \frac{m_{Cl}}{M_{Cl}} 
     \right)
     = 0 $$
     
Тогда:
     
$$ EC = 0.095  
    \left( 
     \frac{m_{NH_4}}{M_N} +
     \frac{2  m_{Ca}}{M_{Ca}} + 
     \frac{2  m_{Mg}}{M_{Mg}} +
     \frac{m_{K}}{M_{K}}
     \right) + 0.19 $$

Где: \
$M$ --- молярная масса\
$m$ --- профиль, в мг/л (ppm)




```python
m_NO3 = 220
m_NH4 = 20
m_P = 40
m_K = 280
m_Ca = 140
m_Mg = 56
m_S = 51.07
m_Cl = 0

M_N = 14.0067
M_Ca = 40.078
M_Mg = 24.305
M_K = 39.0983
M_P = 30.973
M_S = 32.065
M_Cl = 35.45


cations = ((m_NH4/ M_N) + ((2*m_Ca) / M_Ca) + ((2*m_Mg) / M_Mg) + (m_K / M_K) )

anions = ((m_NO3/ M_N) + (m_P / M_P) + ((2*m_S)/ M_S) + (m_Cl/ M_Cl))


EC = (0.095 * cations) + 0.19
print(cations, anions)
print(f'I = {cations-anions:0.2f}')
print(f'EC = {EC:.3f}')

```

    20.183806662456348 20.183620939926474
    I = 0.00
    EC = 2.107


## Ионный баланс профиля

Оптимизация профиля достижением нулевого ионного баланса (сумма катионов и анионов должна быть равна нулю)

Основой является формула ионного баланса

$$ \left(
\frac{m_{NH_4}}{M_N} +
     \frac{2  m_{Ca}}{M_{Ca}} + 
     \frac{2  m_{Mg}}{M_{Mg}} +
     \frac{m_{K}}{M_{K}} 
\right)
     - 
     \left(
     \frac{m_{NO_3}}{M_N} + 
     \frac{m_{P}}{M_{P}} +
     \frac{2m_{S}}{M_{S}} + 
     \frac{m_{Cl}}{M_{Cl}} 
     \right)
     = 0 $$

Баланс производится по сере или кальцию, в зависимости от того что крутим




```python
# Install a pip package in the current Jupyter kernel
import sys
!{sys.executable} -m pip install sympy numpy scipy

import sympy as sym
from sympy import Eq
sym.init_printing()
from IPython.display import Math, display

```

    Requirement already satisfied: sympy in /home/apkawa/.local/lib/python3.9/site-packages (1.7.1)
    Requirement already satisfied: numpy in /usr/lib/python3/dist-packages (1.19.4)
    Collecting scipy
      Downloading scipy-1.6.0-cp39-cp39-manylinux1_x86_64.whl (27.3 MB)
    [K     |████████████████████████████████| 27.3 MB 12.2 MB/s eta 0:00:01
    [?25hRequirement already satisfied: mpmath>=0.19 in /home/apkawa/.local/lib/python3.9/site-packages (from sympy) (1.1.0)
    Installing collected packages: scipy
    Successfully installed scipy-1.6.0



```python
import sympy as sym
sym.init_printing()
elements = ['NO3', 'NH4', 'P', 'K', 'Ca', 'Mg', 'S', 'Cl']

m = dict(zip(elements, sym.symbols([f'm_{e}' for e in elements])))
M = dict(zip(elements, sym.symbols([f'M_{e}' for e in elements])))

repl = {
m['NO3'] : 220,
m['NH4'] : 20,
m['P'] : 40,
m['K'] : 280,    
m['Ca'] : 140,
m['Mg'] : 56,
m['S']: 51.07,
m['Cl']: 0,
    # Молярные массы
M['NO3'] : 14.0067, M['NH4'] : 14.0067, M['Ca'] : 40.078,
M['Mg'] : 24.305, M['K'] : 39.0983, M['P'] : 30.973, M['S'] : 32.065, M['Cl']: 35.45,
}

# Уравнение ионного баланса
Cations = ((m['NH4']/ M['NH4']) + ((2*m['Ca']) / M['Ca']) + ((2*m['Mg']) / M['Mg']) + (m['K'] / M['K']))
Anions = ((m['NO3']/ M['NO3']) + (m['P'] / M['P']) + ((2*m['S'])/ M['S']) + (m['Cl']/ M['Cl']))
Ionic_balance = sym.Eq((Cations - Anions), 0)

I = (Cations - Anions).subs(repl)
print("Проверка что профиль сбалансирован")
print(f"I = {I:0.3f}")

# Решаем уравнение через серу
solved_S = sym.solve([Ionic_balance],(m['S']))[m['S']]

mS = solved_S.subs(repl)

print(f'm_S = {mS:.2f}')

I = (Cations - Anions).subs({**repl, **{m['S']: mS}})
print(f"I = {I:0.3f}")

print("Сера через кальций")

display(sym.Eq(m['S'], solved_S))
r2 = {**repl, **{
    m['NO3'] : 200,
    m['NH4'] : 20,
    m['P'] : 40,
    m['K'] : 180,    
    m['Ca'] : 200,
    m['Mg'] : 50,
}}
mS = solved_S.subs(r2)
print(f'm_S = {mS:.2f}')
r2[m['S']] = mS
I = (Cations - Anions).subs(r2)
print(f"I = {I:0.3f}")

print("Кальций через серу")
r2 = {**r2, **{m['S']: mS}}

solved_Ca = sym.solve([Ionic_balance],(m['Ca']))[m['Ca']]
display(sym.Eq(m['Ca'], solved_Ca))
mCa = solved_Ca.subs(r2)
print(f'm_Ca = {mCa:.2f}')

I = (Cations - Anions).subs({**r2, **{m['Ca']: mCa}})
print(f"I = {I:0.3f}")




```

    Проверка что профиль сбалансирован
    I = 0.000
    m_S = 51.07
    I = 0.000
    Сера через кальций



$\displaystyle m_{S} = \frac{- M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{S} m_{P} - M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NH4} M_{P} M_{S} m_{NO3} + M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NO3} M_{P} M_{S} m_{NH4} + 2 M_{Ca} M_{Cl} M_{K} M_{NH4} M_{NO3} M_{P} M_{S} m_{Mg} + M_{Ca} M_{Cl} M_{Mg} M_{NH4} M_{NO3} M_{P} M_{S} m_{K} - M_{Ca} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{P} M_{S} m_{Cl} + 2 M_{Cl} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{P} M_{S} m_{Ca}}{2 M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{P}}$


    m_S = 73.05
    I = 0.000
    Кальций через серу



$\displaystyle m_{Ca} = \frac{2 M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{P} m_{S} + M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{S} m_{P} + M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NH4} M_{P} M_{S} m_{NO3} - M_{Ca} M_{Cl} M_{K} M_{Mg} M_{NO3} M_{P} M_{S} m_{NH4} - 2 M_{Ca} M_{Cl} M_{K} M_{NH4} M_{NO3} M_{P} M_{S} m_{Mg} - M_{Ca} M_{Cl} M_{Mg} M_{NH4} M_{NO3} M_{P} M_{S} m_{K} + M_{Ca} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{P} M_{S} m_{Cl}}{2 M_{Cl} M_{K} M_{Mg} M_{NH4} M_{NO3} M_{P} M_{S}}$


    m_Ca = 200.00
    I = 0.000



```python
print(solved_S)
print(solved_Ca)
```

    (-M_Ca*M_Cl*M_K*M_Mg*M_NH4*M_NO3*M_S*m_P - M_Ca*M_Cl*M_K*M_Mg*M_NH4*M_P*M_S*m_NO3 + M_Ca*M_Cl*M_K*M_Mg*M_NO3*M_P*M_S*m_NH4 + 2*M_Ca*M_Cl*M_K*M_NH4*M_NO3*M_P*M_S*m_Mg + M_Ca*M_Cl*M_Mg*M_NH4*M_NO3*M_P*M_S*m_K - M_Ca*M_K*M_Mg*M_NH4*M_NO3*M_P*M_S*m_Cl + 2*M_Cl*M_K*M_Mg*M_NH4*M_NO3*M_P*M_S*m_Ca)/(2*M_Ca*M_Cl*M_K*M_Mg*M_NH4*M_NO3*M_P)
    (2*M_Ca*M_Cl*M_K*M_Mg*M_NH4*M_NO3*M_P*m_S + M_Ca*M_Cl*M_K*M_Mg*M_NH4*M_NO3*M_S*m_P + M_Ca*M_Cl*M_K*M_Mg*M_NH4*M_P*M_S*m_NO3 - M_Ca*M_Cl*M_K*M_Mg*M_NO3*M_P*M_S*m_NH4 - 2*M_Ca*M_Cl*M_K*M_NH4*M_NO3*M_P*M_S*m_Mg - M_Ca*M_Cl*M_Mg*M_NH4*M_NO3*M_P*M_S*m_K + M_Ca*M_K*M_Mg*M_NH4*M_NO3*M_P*M_S*m_Cl)/(2*M_Cl*M_K*M_Mg*M_NH4*M_NO3*M_P*M_S)


## ЕС профиля

Коррекция профиля по EC производится по формуле Зоневельда

$$ EC = 0.095  
    \left( 
     \frac{m_{NH_4}  r}{M_N} +
     \frac{2  m_{Ca} r}{M_{Ca}} + 
     \frac{2  m_{Mg} r}{M_{Mg}} +
     \frac{m_{K} r}{M_{K}}
     \right) + 0.19 $$
     
где $r$ - это коэфициент приведения


```python
elements = ['NO3', 'NH4', 'P', 'K', 'Ca', 'Mg', 'S', 'Cl']

r = sym.symbols('r')
EC, NH4NO3, KMg, KCa, KN, PN, N = sym.symbols(['EC', 'K_NH4NO3', 'K_KMg', 'K_KCa', 'K_KN', 'K_PN', 'm_N'])

m = dict(zip(elements, sym.symbols([f'm_{e}' for e in elements])))
M = dict(zip(elements, sym.symbols([f'M_{e}' for e in elements])))

repl = {
    r: 1,
    m['NO3'] : 200,
    m['NH4'] : 20,
    m['P'] : 40,
    m['K'] : 180,    
    m['Ca'] : 200,
    m['Mg'] : 50,
    m['S']: 72.44,
    m['Cl']: 0.0,
    # Молярные массы
    M['NO3'] : 14.0067, M['NH4'] : 14.0067, M['Ca'] : 40.078,
    M['Mg'] : 24.305, M['K'] : 39.0983, M['P'] : 30.0983, M['S'] : 32.065, M['Cl']: 35.45,
}

# Формулы коэфициентов 

NH4NO3f = sym.Eq(m['NH4'] / m['NO3'], NH4NO3)
Nf = sym.Eq(m['NH4'] + m['NO3'], N)


Sum_k = sym.Eq(sum([N, m['K'], m['Ca'], m['Mg']]), 1)
KCaf = sym.Eq(m['K'] / m['Ca'], KCa)
KMgf = sym.Eq(m['K'] / m['Mg'], KMg)
KNf = sym.Eq(m['K'] / N, KN)


# Решаем обратную задачу перевода из коэфициентов в элементы

# Решаем систему уравнений
NH4NO3_s = sym.solve([NH4NO3f, Nf], [m['NH4'], m['NO3']])

print("Решаем систему уравнений для NH3 и NO3")
display({
    Nf,
    NH4NO3f,
    
})
print("Результат")
display(sym.Eq(m['NH4'], NH4NO3_s[m['NH4']]))
display(sym.Eq(m['NO3'], NH4NO3_s[m['NO3']]))


Elements = [N, m['K'], m['Ca'], m['Mg']]
NKCaMg_s = sym.solve([Sum_k, KNf, KCaf, KMgf], Elements)

print("Решаем систему уравнений для N, K, Ca, Mg")
display({
    Sum_k, KNf, KCaf, KMgf
})
print("Результат")
for e in Elements:
    display(sym.Eq(e, NKCaMg_s[e]))



# Уравнение ионного баланса
Cations = (
    ((m['NH4'] * r) / M['NH4']) 
           + ((2*m['Ca']*r) / M['Ca']) 
           + ((2*m['Mg']*r) / M['Mg']) 
           + ((m['K']*r) / M['K'])
          )
Anions = ((m['NO3']/ M['NO3']) + (m['P'] / M['P']) + ((2*m['S'])/ M['S']) + (m['Cl']/ M['Cl']))

ECf = sym.Eq(EC, 0.095 * Cations + 0.19)

# Вычисляем текущий EC
ECv = ECf.subs(repl).rhs
print('Текущий EC')
print(f'EC = {ECv:0.3f}')

# Вычисляем существующие коэфициенты

r_k = {
    N: repl[m['NO3']] + repl[m['NH4']],
    NH4NO3: repl[m['NH4']] / repl[m['NO3']],
    KCa: repl[m['K']] / repl[m['Ca']],
    KMg: repl[m['K']] / repl[m['Mg']],
}
r_k[KN] = repl[m['K']] / r_k[N]
    

print(r_k)
print("Вычисляем % элементов по коэфициентам")

rN = NKCaMg_s[N].subs(r_k)
rK = NKCaMg_s[m['K']].subs(r_k)
rCa = NKCaMg_s[m['Ca']].subs(r_k)
rMg = NKCaMg_s[m['Mg']].subs(r_k)

rNH4 = NH4NO3_s[m['NH4']].subs({**r_k, N: rN})
rNO3 = NH4NO3_s[m['NO3']].subs({**r_k, N: rN})


print(f'rN={rN:.4f} rNO3={rNO3:.4f} rNH4={rNH4:.4f} rK={rK:.4f} rCa={rCa:.4f} rMg={rMg:.4f}')


# Решаем уравнение
print("Решаем уравнение с неизвестной r")
display(ECf)
solved_r = sym.solve([ECf],(r))[r]

display(sym.Eq(r, solved_r))

ECnew = ECv
r2 = {**repl, 
    EC: ECnew,
      
    m['NH4'] : rNH4,
    m['NO3']: rNO3,
    m['K'] : rK,    
    m['Ca'] : rCa,
    m['Mg'] : rMg,
                  }

# Вычисляем коэфициент
r_k = solved_r.subs(r2)

print(f'r = {r_k:0.2f}')


print('Проверяем новый ЕС')
EC_p = EC.subs({**r2, 
                r: r_k
                  })

print(f'EC = {EC_p:0.3f}')


print('Считаем новый профиль')
r3 = dict(repl)
for e in ['NO3', 'NH4', 'K', 'Ca', 'Mg']:
    
    mE = r2[m[e]] * r_k
    r3[m[e]] = mE
    print(f'{e}={mE:.2f}')
    
I = (Cations - Anions).subs(r3)
print(f"I = {I:0.3f}")    

mS = solved_S.subs(r3)
print(f'S={r3[m["S"]]:0.2f} -> {mS:0.2f}')
    
# Фосфор - неизменен, сера пересчитывается по балансу

print("Пересчитываем на EC=1.5")

r2 = {**r2, 
    EC: 1.5,
    m['NH4'] : rNH4,
    m['K'] : rK,    
    m['Ca'] : rCa,
    m['Mg'] : rMg,
                  }

# Вычисляем коэфициент
r_k = solved_r.subs(r2)

print(f'r = {r_k:0.2f}')


print('Проверяем новый ЕС')
EC_p = EC.subs({**r2, 
                r: r_k
                  })

print(f'EC = {EC_p:0.3f}')


print('Считаем новый профиль')
r3 = dict(repl)
for e in ['NO3', 'NH4', 'K', 'Ca', 'Mg']:
    
    mE = r2[m[e]] * r_k
    r3[m[e]] = mE
    print(f'{e}={mE:.2f}')
    
print(f"NH4/NO3 = {r3[m['NH4']] / r3[m['NO3']]}")
I = (Cations - Anions).subs(r3)
print(f"I = {I:0.3f}")    

mS = solved_S.subs(r3)
print(f'S={r3[m["S"]]:0.2f} -> {mS:0.2f}')

I = (Cations - Anions).subs({**r3, m['S']: mS})
print(f"I = {I:0.3f}")


```

    Решаем систему уравнений для NH3 и NO3



$\displaystyle \left\{\frac{m_{NH4}}{m_{NO3}} = K_{NH4NO3}, m_{NH4} + m_{NO3} = m_{N}\right\}$


    Результат



$\displaystyle m_{NH4} = \frac{K_{NH4NO3} m_{N}}{K_{NH4NO3} + 1}$



$\displaystyle m_{NO3} = \frac{m_{N}}{K_{NH4NO3} + 1}$


    Решаем систему уравнений для N, K, Ca, Mg



$\displaystyle \left\{\frac{m_{K}}{m_{Ca}} = K_{KCa}, \frac{m_{K}}{m_{Mg}} = K_{KMg}, \frac{m_{K}}{m_{N}} = K_{KN}, m_{Ca} + m_{K} + m_{Mg} + m_{N} = 1\right\}$


    Результат



$\displaystyle m_{N} = \frac{K_{KCa} K_{KMg}}{K_{KCa} K_{KMg} K_{KN} + K_{KCa} K_{KMg} + K_{KCa} K_{KN} + K_{KMg} K_{KN}}$



$\displaystyle m_{K} = \frac{K_{KCa} K_{KMg} K_{KN}}{K_{KCa} K_{KMg} K_{KN} + K_{KCa} K_{KMg} + K_{KCa} K_{KN} + K_{KMg} K_{KN}}$



$\displaystyle m_{Ca} = \frac{K_{KMg} K_{KN}}{K_{KCa} K_{KMg} K_{KN} + K_{KCa} K_{KMg} + K_{KCa} K_{KN} + K_{KMg} K_{KN}}$



$\displaystyle m_{Mg} = \frac{K_{KCa} K_{KN}}{K_{KCa} K_{KMg} K_{KN} + K_{KCa} K_{KMg} + K_{KCa} K_{KN} + K_{KMg} K_{KN}}$


    Текущий EC
    EC = 2.102
    {m_N: 220, K_NH4NO3: 0.1, K_KCa: 0.9, K_KMg: 3.6, K_KN: 0.8181818181818182}
    Вычисляем % элементов по коэфициентам
    rN=0.3385 rNO3=0.3077 rNH4=0.0308 rK=0.2769 rCa=0.3077 rMg=0.0769
    Решаем уравнение с неизвестной r



$\displaystyle EC = 0.19 + \frac{0.095 m_{NH4} r}{M_{NH4}} + \frac{0.19 m_{Mg} r}{M_{Mg}} + \frac{0.095 m_{K} r}{M_{K}} + \frac{0.19 m_{Ca} r}{M_{Ca}}$



$\displaystyle r = \frac{200.0 EC M_{Ca} M_{K} M_{Mg} M_{NH4} - 38.0 M_{Ca} M_{K} M_{Mg} M_{NH4}}{19.0 M_{Ca} M_{K} M_{Mg} m_{NH4} + 38.0 M_{Ca} M_{K} M_{NH4} m_{Mg} + 19.0 M_{Ca} M_{Mg} M_{NH4} m_{K} + 38.0 M_{K} M_{Mg} M_{NH4} m_{Ca}}$


    r = 650.00
    Проверяем новый ЕС
    EC = 2.102
    Считаем новый профиль
    NO3=200.00
    NH4=20.00
    K=180.00
    Ca=200.00
    Mg=50.00
    I = 0.000
    S=72.44 -> 72.45
    Пересчитываем на EC=1.5
    r = 445.34
    Проверяем новый ЕС
    EC = 1.500
    Считаем новый профиль
    NO3=137.03
    NH4=13.70
    K=123.32
    Ca=137.03
    Mg=34.26
    NH4/NO3 = 0.100000000000000
    I = -1.841
    S=72.44 -> 42.93
    I = 0.000



```python
# Печатаем уравнения для кодирования
for e, f in NH4NO3_s.items():
    print(f'{e} = {f}')
for e, f in NKCaMg_s.items():
    print(f'{e} = {f}')
    
print(f'r = {solved_r}')
```

    m_NH4 = K_NH4NO3*m_N/(K_NH4NO3 + 1)
    m_NO3 = m_N/(K_NH4NO3 + 1)
    m_N = K_KCa*K_KMg/(K_KCa*K_KMg*K_KN + K_KCa*K_KMg + K_KCa*K_KN + K_KMg*K_KN)
    m_K = K_KCa*K_KMg*K_KN/(K_KCa*K_KMg*K_KN + K_KCa*K_KMg + K_KCa*K_KN + K_KMg*K_KN)
    m_Ca = K_KMg*K_KN/(K_KCa*K_KMg*K_KN + K_KCa*K_KMg + K_KCa*K_KN + K_KMg*K_KN)
    m_Mg = K_KCa*K_KN/(K_KCa*K_KMg*K_KN + K_KCa*K_KMg + K_KCa*K_KN + K_KMg*K_KN)
    r = (200.0*EC*M_Ca*M_K*M_Mg*M_NH4 - 38.0*M_Ca*M_K*M_Mg*M_NH4)/(19.0*M_Ca*M_K*M_Mg*m_NH4 + 38.0*M_Ca*M_K*M_NH4*m_Mg + 19.0*M_Ca*M_Mg*M_NH4*m_K + 38.0*M_K*M_Mg*M_NH4*m_Ca)


## Расчет навески



```python
'''
Решение через уравнение
'''
elements = ['NO3', 'NH4', 'P', 'K', 'Ca', 'Mg', 'S', 'Cl']
Fertilizers = [
    'Ca(NO3)2',
       
    'KNO3',
       
    'NH4NO3',
        
    'MgSO4',
        
    'KH2PO4',
        
    'K2SO4',
        
   # 'Mg(NO3)2',
    
    'CaCl2',
    
    
]

F = dict(zip(Fertilizers, sym.symbols([f'F_{e}' for e in Fertilizers])))

m = dict(zip(elements, sym.symbols([f'm_{e}' for e in elements])))
M = dict(zip(elements, sym.symbols([f'M_{e}' for e in elements])))



F_elems = [
    #['NO3', ['Ca(NO3)2', 'KNO3', 'NH4NO3']],
    ['NH4', ['NH4NO3']],
    ['P', ['KH2PO4']],
    ['K', ['KNO3', 'KH2PO4', 'K2SO4']],
    ['Ca', ['CaCl2', 'Ca(NO3)2']],
    ['Mg', ['MgSO4', 'Mg(NO3)2']],
    ['S', ['MgSO4', 'K2SO4']],
    ['Cl', ['CaCl2']],
    
]
System = []

for [el, fer] in F_elems:
    for _f in fer:
        if _f in Fertilizers:
            F[f'{_f}_{el}'] = sym.symbols(f'F_{_f}_{el}')
        
    System.append(
        Eq(m[el],
           sum([F[_f]*F[f'{_f}_{el}'] for _f in fer if _f in Fertilizers])
                    ))
    

print("Решаем систему уравнений")
display(System)

ferts = sym.solve(System, [F[_f] for _f in Fertilizers])


print("Уравнения по каждому удобрению")
for _f in Fertilizers:
    if _f in Fertilizers:
        display(
            Eq(F[_f], ferts[F[_f]])
        )
    
    

repl = {
    #NPK
    m['NO3'] : 200,
    m['NH4'] : 20,
    m['P'] : 40,
    m['K'] : 180,    
    m['Ca'] : 200,
    m['Mg'] : 50,
    m['S']: 68.52,
    m['Cl']: 10,
    # Молярные массы
    M['NO3'] : 14.0067, M['NH4'] : 14.0067, M['Ca'] : 40.078,
    M['Mg'] : 24.305, M['K'] : 39.0983, M['P'] : 30.0983, M['S'] : 32.065, M['Cl']: 35.45,
}
repl[m['S']] = solved_S.subs(repl)
ferts_perc ={
    # Процентовки
    'Ca(NO3)2_Ca':16.972,
    'Ca(NO3)2_NO3':11.863,
       
    'KNO3_K':38.672,
    'KNO3_NO3':13.854,
       
    'NH4NO3_NO3':17.499,
    'NH4NO3_NH4':17.499,
        
    'MgSO4_Mg':9.861,
    'MgSO4_S':13.010,
        
    'KH2PO4_K':28.731,
    'KH2PO4_P':22.761,
        
    'K2SO4_K':44.874,
    'K2SO4_S':18.401,
        
    'Mg(NO3)2_Mg': 9.479,
    'Mg(NO3)2_NO3': 10.925,

    'CaCl2_Ca':18.294,
    'CaCl2_Cl':32.366,
}

for [k, v] in ferts_perc.items():
    if k in F:
        repl[F[k]] = v


print("Подставля процентовку удобрений получаем расчет, в г")
weights = {}
for _f in Fertilizers:
    w = ferts[F[_f]].subs(repl)
    display(Eq(F[_f], round(w,4)))
    weights[_f] = w


print("Проверка профиля")

for _e in elements:
    Ep = repl[m[_e]]
    Ef = 0
    for _f in Fertilizers:
        k = f'{_f}_{_e}'
        if k in ferts_perc and _f in weights:
            Ef += weights[_f] * (ferts_perc[k])
    
    print(f'{_e} = {Ep} - {Ef:0.2f} = {round(Ef - Ep,2)}')
    




```

    Решаем систему уравнений



$\displaystyle \left[ m_{NH4} = F_{NH4NO3} F_{NH4NO3 NH4}, \  m_{P} = F_{KH2PO4} F_{KH2PO4 P}, \  m_{K} = F_{K2SO4} F_{K2SO4 K} + F_{KH2PO4} F_{KH2PO4 K} + F_{KNO3} F_{KNO3 K}, \  m_{Ca} = F_{Ca(NO3)2} F_{Ca(NO3)2 Ca} + F_{CaCl2} F_{CaCl2 Ca}, \  m_{Mg} = F_{MgSO4} F_{MgSO4 Mg}, \  m_{S} = F_{K2SO4} F_{K2SO4 S} + F_{MgSO4} F_{MgSO4 S}, \  m_{Cl} = F_{CaCl2} F_{CaCl2 Cl}\right]$


    Уравнения по каждому удобрению



$\displaystyle F_{Ca(NO3)2} = \frac{- F_{CaCl2 Ca} m_{Cl} + F_{CaCl2 Cl} m_{Ca}}{F_{Ca(NO3)2 Ca} F_{CaCl2 Cl}}$



$\displaystyle F_{KNO3} = \frac{- F_{K2SO4 K} F_{KH2PO4 P} F_{MgSO4 Mg} m_{S} + F_{K2SO4 K} F_{KH2PO4 P} F_{MgSO4 S} m_{Mg} - F_{K2SO4 S} F_{KH2PO4 K} F_{MgSO4 Mg} m_{P} + F_{K2SO4 S} F_{KH2PO4 P} F_{MgSO4 Mg} m_{K}}{F_{K2SO4 S} F_{KH2PO4 P} F_{KNO3 K} F_{MgSO4 Mg}}$



$\displaystyle F_{NH4NO3} = \frac{m_{NH4}}{F_{NH4NO3 NH4}}$



$\displaystyle F_{MgSO4} = \frac{m_{Mg}}{F_{MgSO4 Mg}}$



$\displaystyle F_{KH2PO4} = \frac{m_{P}}{F_{KH2PO4 P}}$



$\displaystyle F_{K2SO4} = \frac{F_{MgSO4 Mg} m_{S} - F_{MgSO4 S} m_{Mg}}{F_{K2SO4 S} F_{MgSO4 Mg}}$



$\displaystyle F_{CaCl2} = \frac{m_{Cl}}{F_{CaCl2 Cl}}$


    Подставля процентовку удобрений получаем расчет, в г



$\displaystyle F_{Ca(NO3)2} = 11.4511$



$\displaystyle F_{KNO3} = 3.2255$



$\displaystyle F_{NH4NO3} = 1.1429$



$\displaystyle F_{MgSO4} = 5.0705$



$\displaystyle F_{KH2PO4} = 1.7574$



$\displaystyle F_{K2SO4} = 0.1064$



$\displaystyle F_{CaCl2} = 0.309$


    Проверка профиля
    NO3 = 200 - 200.53 = 0.53
    NH4 = 20 - 20.00 = 0
    P = 40 - 40.00 = 0
    K = 180 - 180.00 = 0.0
    Ca = 200 - 200.00 = 0.0
    Mg = 50 - 50.00 = 0
    S = 67.9239233594011 - 67.92 = 0
    Cl = 10 - 10.00 = 0



```python
"""
Алгоритмическое решение
"""

elements = ['NO3', 'NH4', 'P', 'K', 'Ca', 'Mg', 'S', 'Cl']
Fertilizers = [
    'K2SO4',
    'Ca(NO3)2',   
    'KNO3',     
    'NH4NO3',
    
    
        
    'MgSO4',
       
    'KH2PO4',
        
    
        
    #'Mg(NO3)2',
    'CaCl2',
    
    
]

F_elems = dict([
    ['NO3', ['Ca(NO3)2', 'KNO3', 'NH4NO3', 'Mg(NO3)2']],
    ['NH4', ['NH4NO3']],
    ['P', ['KH2PO4']],
    ['K', ['KNO3', 'KH2PO4', 'K2SO4']],
    ['Ca', ['CaCl2', 'Ca(NO3)2']],
    ['Mg', ['MgSO4', 'Mg(NO3)2']],
    ['S', ['MgSO4', 'K2SO4']],
    ['Cl', ['CaCl2']],    
]    )
npk = {
    'NO3' : 200,
    'NH4' : 20,
    'P' : 40,
    'K' : 180,    
    'Ca' : 200,
    'Mg' : 56,
    'Cl': 10,  
    'S': 67.92,
}

ferts_perc ={
    # Процентовки
    'Ca(NO3)2_Ca':16.972,
    'Ca(NO3)2_NO3':11.863,
       
    'KNO3_K':38.672,
    'KNO3_NO3':13.854,
       
    'NH4NO3_NO3':17.499,
    'NH4NO3_NH4':17.499,
        
    'MgSO4_Mg':9.861,
    'MgSO4_S':13.010,
        
    'KH2PO4_K':28.731,
    'KH2PO4_P':22.761,
        
    'K2SO4_K':44.874,
    'K2SO4_S':18.401,
        
    'Mg(NO3)2_Mg': 9.479,
    'Mg(NO3)2_NO3': 10.925,

    'CaCl2_Ca':18.294,
    'CaCl2_Cl':32.366,
}
for (k, v) in list(ferts_perc.items()):
    f, el = k.split('_')
    if f not in ferts_perc:
        ferts_perc[f] = {}
    ferts_perc[f][el] = v
    
#print(ferts_perc)
  
    

dNPK = dict(sorted(npk.items(), key=lambda i: i[1]))

#print(dNPK)


weights = {}

for el in dNPK:
    for _f in Fertilizers:
        
        if _f not in F_elems[el]:
            continue
        if el == 'NO3':
            continue
        if _f in weights or _f not in Fertilizers:
            continue
        perc = dict(ferts_perc[_f])
        w = dNPK[el] / perc.pop(el)
        
        print(f'{_f} = {round(w,4)}')
        for _el, _p in perc.items():
            dNPK[_el] -= w * _p
        weights[_f] = w

        


print("Проверка профиля")

for _e in elements:
    Ep = npk[_e]
    Ef = 0
    for _f in Fertilizers:
        k = f'{_f}_{_e}'
        if k in ferts_perc and _f in weights:
            Ef += weights[_f] * (ferts_perc[k])
    
    print(f'{_e} = {Ep:0.2f} - {Ef:0.2f} = {round(Ep - Ef,2)}')
    

# На данный момент оно собирает неточно

```

    CaCl2 = 0.309
    NH4NO3 = 1.1429
    KH2PO4 = 1.7574
    MgSO4 = 5.6789
    K2SO4 = -0.3241
    KNO3 = 3.7249
    Ca(NO3)2 = 11.4511
    Проверка профиля
    NO3 = 200.00 - 207.45 = -7.45
    NH4 = 20.00 - 20.00 = 0.0
    P = 40.00 - 40.00 = 0.0
    K = 180.00 - 180.00 = 0.0
    Ca = 200.00 - 200.00 = 0.0
    Mg = 56.00 - 56.00 = 0.0
    S = 67.92 - 67.92 = 0.0
    Cl = 10.00 - 10.00 = 0.0



```python
"""
Решение системами линейных уравнений
"""
# Пока не работает
elements = ['NO3', 'NH4', 'P', 'K', 'Ca', 'Mg', 'S', 'Cl']
Fertilizers = [
    'K2SO4',
    'Ca(NO3)2',   
    'KNO3',     
    'NH4NO3',
         
    'MgSO4',      
    'KH2PO4',
    
    #'Mg(NO3)2',
    'CaCl2',
    
]

F_elems = dict([
    ['NO3', ['Ca(NO3)2', 'KNO3', 'NH4NO3', 'Mg(NO3)2']],
    ['NH4', ['NH4NO3']],
    ['P', ['KH2PO4']],
    ['K', ['KNO3', 'KH2PO4', 'K2SO4']],
    ['Ca', ['CaCl2', 'Ca(NO3)2']],
    ['Mg', ['MgSO4', 'Mg(NO3)2']],
    ['S', ['MgSO4', 'K2SO4']],
    ['Cl', ['CaCl2']],    
]    )
npk = {
    'NO3' : 200,
    'NH4' : 20,
    'P' : 40,
    'K' : 180,    
    'Ca' : 200,
    'Mg' : 56,
    'Cl': 10,  
    'S': 67.92,
}

ferts_perc ={
    # Процентовки
    'Ca(NO3)2_Ca':16.972,
    'Ca(NO3)2_NO3':11.863,
       
    'KNO3_K':38.672,
    'KNO3_NO3':13.854,
       
    'NH4NO3_NO3':17.499,
    'NH4NO3_NH4':17.499,
        
    'MgSO4_Mg':9.861,
    'MgSO4_S':13.010,
        
    'KH2PO4_K':28.731,
    'KH2PO4_P':22.761,
        
    'K2SO4_K':44.874,
    'K2SO4_S':18.401,
        
    'Mg(NO3)2_Mg': 9.479,
    'Mg(NO3)2_NO3': 10.925,

    'CaCl2_Ca':18.294,
    'CaCl2_Cl':32.366,
}

for (k, v) in list(ferts_perc.items()):
    f, el = k.split('_')
    if f not in ferts_perc:
        ferts_perc[f] = {}
    ferts_perc[f][el] = v

# Решение

A = []

for el, ferts in F_elems.items():
    r = []
    for f in Fertilizers:
        if f not in ferts:
            r.append(0)
        else:
            r.append(ferts_perc[f][el])
    A.append(r)       

B = [[npk[el]] for el in F_elems]

print(A)
print(B)

print(len(A[0]), len(B))

A_len = len(A[0])
B_len = len(B)

if A_len < B_len:
    for i in range(B_len - A_len):
        for r in A:
            r.append(1)        

r = [i[0] for i in numpy.linalg.solve(A,B)]

print(r[-1])
weights = dict(zip(Fertilizers, r))

for f, w in weights.items():
    print(f'{f} = {w:.2f}')
# Проверка

print("Проверка профиля")

for _e in elements:
    Ep = npk[_e]
    Ef = 0
    for _f in Fertilizers:
        k = f'{_f}_{_e}'
        if k in ferts_perc and _f in weights:
            Ef += weights[_f] * (ferts_perc[k])
    
    print(f'{_e} = {Ep:0.2f} - {Ef:0.2f} = {round(Ep - Ef,2)}')
  

```

    [[0, 11.863, 13.854, 17.499, 0, 0, 0], [0, 0, 0, 17.499, 0, 0, 0], [0, 0, 0, 0, 0, 22.761, 0], [44.874, 0, 38.672, 0, 0, 28.731, 0], [0, 16.972, 0, 0, 0, 0, 18.294], [0, 0, 0, 0, 9.861, 0, 0], [18.401, 0, 0, 0, 13.01, 0, 0], [0, 0, 0, 0, 0, 0, 32.366]]
    [[200], [20], [40], [180], [200], [56], [67.92], [10]]
    7 8
    15.236063909134588
    K2SO4 = -0.06
    Ca(NO3)2 = 11.06
    KNO3 = 3.52
    NH4NO3 = 0.27
    MgSO4 = 4.13
    KH2PO4 = 1.09
    CaCl2 = -0.16
    Проверка профиля
    NO3 = 200.00 - 184.76 = 15.24
    NH4 = 20.00 - 4.76 = 15.24
    P = 40.00 - 24.76 = 15.24
    K = 180.00 - 164.76 = 15.24
    Ca = 200.00 - 184.76 = 15.24
    Mg = 56.00 - 40.76 = 15.24
    S = 67.92 - 52.68 = 15.24
    Cl = 10.00 - -5.24 = 15.24



```python
import numpy.linalg

"""
x - y = -5
2x + y = -7
"""

a = [[1, -1], [2, 1]]
b = [[-5], [-7]]

r = numpy.linalg.solve(a,b)
print(f"x={r[0][0]} y={r[1][0]}")

"""
x - y + z = -5
2x + y + z = -7
"""

a = [[1, -1, 1], [2, 1, 1], [1,1,1]]
b = [[-5], [-7], [0]]

r = numpy.linalg.solve(a,b)
print(f"x={r[0][0]} y={r[1][0]} z={r[2][0]}")

print(-10-4+9)
print(2*-10+4+9)

"""
x - y = -5
2x + y = -7
2x + y = 10
"""

a = [[1, -1, 1], [2, 1, 1], [1, 1, 1]]
b = [[-5], [-7], [10]]

r = numpy.linalg.solve(a,b)
print(f"x={r[0][0]} y={r[1][0]} z={r[2][0]}")

print(-10-4+9)
print(2*-10+4+9)

"""
17.33x = 200
17.33x = 20
"""

a = [[17.33], [17.33]]
b = [200, 20]

w = numpy.linalg.lstsq(a,b)[0][0]
print(w)


```

    x=-4.0 y=1.0
    x=-7.0 y=2.5 z=4.5
    -5
    -7
    x=-17.0 y=7.5 z=19.5
    -5
    -7
    6.347374495095211
    110.0


    <ipython-input-51-5da7e57cab58>:51: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
    To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
      w = numpy.linalg.lstsq(a,b)[0][0]



```python
import numpy as np

# https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linalg.lstsq.html#numpy.linalg.lstsq
x = np.array([0, 1, 2, 3])
y = np.array([-1, 0.2, 0.9, 2.1])
A = np.vstack([x, np.ones(len(x))]).T
print(A)
r = np.linalg.lstsq(A, y)
print(r)
m, c = r[0]

print(m, c)

```

    [[0. 1.]
     [1. 1.]
     [2. 1.]
     [3. 1.]]
    (array([ 1.  , -0.95]), array([0.05]), 2, array([4.10003045, 1.09075677]))
    1.0000000000000002 -0.9499999999999996


    <ipython-input-38-694e3cc76ac4>:7: FutureWarning: `rcond` parameter will change to the default of machine precision times ``max(M, N)`` where M and N are the input matrix dimensions.
    To use the future default and silence this warning we advise to pass `rcond=None`, to keep using the old, explicitly pass `rcond=-1`.
      r = np.linalg.lstsq(A, y)



```python
import numpy as np

A = [[0, 11.863, 13.854, 17.499, 0, 0, 0], [0, 0, 0, 17.499, 0, 0, 0], [0, 0, 0, 0, 0, 22.761, 0], [44.874, 0, 38.672, 0, 0, 28.731, 0], [0, 16.972, 0, 0, 0, 0, 18.294], [0, 0, 0, 0, 9.861, 0, 0], [18.401, 0, 0, 0, 13.01, 0, 0], [0, 0, 0, 0, 0, 0, 32.366]]
B = [[200], [20], [40], [180], [200], [56], [67.92], [10]]
A_len = len(A[0])
B_len = len(B)

r = np.linalg.qr([A, B])
print(r)
```

3077fd839adf2923770110afcfdb413811f327b1
ipynb
Jupyter Notebook
docs/model_v3.ipynb
Apkawa/react-fertilizer-calculator
26adb8fe6d9b799302d8430aa492c98f91878ebe
MIT
2021-02-27T22:00:47.000Z
2021-05-12T16:23:01.000Z
docs/model_v3.ipynb
Apkawa/react-fertilizer-calculator
26adb8fe6d9b799302d8430aa492c98f91878ebe
MIT
docs/model_v3.ipynb
Apkawa/react-fertilizer-calculator
26adb8fe6d9b799302d8430aa492c98f91878ebe
MIT
2020-11-10T13:09:10.000Z
2020-11-10T13:09:10.000Z
Qwen/Qwen-72B
1. YES
2. YES