Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -708,51 +708,116 @@ fertilizers_db = {
|
|
708 |
|
709 |
|
710 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
711 |
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
|
|
|
|
|
|
|
|
724 |
|
725 |
-
def optimize_manual(calculator, target_ppm, max_iter=100):
|
726 |
-
"""Грубый подбор масс удобрений под целевой состав."""
|
727 |
-
current_ppm = calculator.calculate_ppm()
|
728 |
-
fertilizers = calculator.fertilizers.copy()
|
729 |
-
|
730 |
-
for _ in range(max_iter):
|
731 |
-
adjusted = False
|
732 |
-
for i, (name, grams) in enumerate(fertilizers):
|
733 |
-
for element, target in target_ppm.items():
|
734 |
-
current = current_ppm.get(element, 0)
|
735 |
-
if current < target:
|
736 |
-
# Увеличиваем массу удобрения, содержащего этот элемент
|
737 |
-
if element in fertilizers_db[name]:
|
738 |
-
fertilizers[i] = (name, grams * 1.05) # +5%
|
739 |
-
adjusted = True
|
740 |
-
if not adjusted:
|
741 |
-
break
|
742 |
-
calculator.fertilizers = fertilizers
|
743 |
-
current_ppm = calculator.calculate_ppm()
|
744 |
-
|
745 |
-
return calculator
|
746 |
|
747 |
|
748 |
|
749 |
|
|
|
|
|
|
|
|
|
750 |
|
751 |
-
target = {"N (NO3-)": 150, "Ca": 200, "Mg": 50}
|
752 |
-
calc = HydroCalculator(10)
|
753 |
-
calc.add_fertilizer("Кальциевая селитра", 1) # Начальное приближение: 1 г
|
754 |
-
calc.add_fertilizer("Сульфат магния", 1)
|
755 |
-
optimize_manual(calc, target)
|
756 |
calc.print_report()
|
757 |
|
758 |
|
@@ -762,94 +827,6 @@ calc.print_report()
|
|
762 |
|
763 |
|
764 |
|
765 |
-
# Молярные массы (г/моль)
|
766 |
-
MOLAR_MASSES = {
|
767 |
-
'N (NO3-)': 62.0, # NO3⁻
|
768 |
-
'N (NH4+)': 18.0, # NH4⁺
|
769 |
-
'K': 39.1,
|
770 |
-
'Ca': 40.1,
|
771 |
-
'Mg': 24.3,
|
772 |
-
'S': 96.1, # SO4²⁻
|
773 |
-
'P': 95.0, # H2PO4⁻
|
774 |
-
}
|
775 |
-
|
776 |
-
# Молярная проводимость (λ₀) в мкСм·см²/моль
|
777 |
-
ION_CONDUCTIVITY = {
|
778 |
-
'N (NO3-)': 71.4,
|
779 |
-
'N (NH4+)': 73.5,
|
780 |
-
'K': 73.5,
|
781 |
-
'Ca': 119.0,
|
782 |
-
'Mg': 106.0,
|
783 |
-
'S': 160.0, # Вклад SO4²⁻
|
784 |
-
'P': 33.0, # Вклад H2PO4⁻
|
785 |
-
}
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
def _ppm_to_molarity(self, ppm, element):
|
790 |
-
"""Конвертирует ppm в моль/л."""
|
791 |
-
if element not in MOLAR_MASSES:
|
792 |
-
return 0.0
|
793 |
-
return ppm / (MOLAR_MASSES[element] * 1000) # ppm = мг/л → моль/л
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
def calculate_ec_exact(self):
|
799 |
-
"""Точный расчёт EC по молярной проводимости"""
|
800 |
-
MOLAR_MASSES = {
|
801 |
-
'N (NO3-)': 62.0,
|
802 |
-
'N (NH4+)': 18.0,
|
803 |
-
'K': 39.1,
|
804 |
-
'Ca': 40.1,
|
805 |
-
'Mg': 24.3,
|
806 |
-
'S': 96.1, # если это SO4²⁻, то правильнее ~96.1 (SO4)
|
807 |
-
'P': 95.0, # если это H2PO4⁻, уточните
|
808 |
-
}
|
809 |
-
|
810 |
-
ION_CONDUCTIVITY = {
|
811 |
-
'N (NO3-)': 71.4,
|
812 |
-
'N (NH4+)': 73.5,
|
813 |
-
'K': 73.5,
|
814 |
-
'Ca': 119.0,
|
815 |
-
'Mg': 106.0,
|
816 |
-
'S': 160.0, # для SO4²⁻
|
817 |
-
'P': 33.0, # ориентировочно для H2PO4⁻
|
818 |
-
}
|
819 |
-
|
820 |
-
ppm = self.calculate_ppm()
|
821 |
-
ec = 0.0 # мкСм/см
|
822 |
-
|
823 |
-
for element, ppm_value in ppm.items():
|
824 |
-
if element in MOLAR_MASSES and element in ION_CONDUCTIVITY:
|
825 |
-
molarity = (ppm_value / 1000) / MOLAR_MASSES[element] # г/л → моль/л
|
826 |
-
ec += molarity * ION_CONDUCTIVITY[element]
|
827 |
-
|
828 |
-
return ec / 1000 # мкСм/см → мСм/см
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
calc = HydroCalculator(10)
|
836 |
-
calc.add_fertilizer("Кальциевая селитра", 100) # Ca(NO3)2
|
837 |
-
calc.add_fertilizer("Сульфат магния", 50) # MgSO4
|
838 |
-
|
839 |
-
ppm = calc.calculate_ppm()
|
840 |
-
ec = calc.calculate_ec_exact()
|
841 |
-
|
842 |
-
print(f"Точный EC: {ec:.2f} mS/cm")
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
|
854 |
|
855 |
|
|
|
708 |
|
709 |
|
710 |
|
711 |
+
class HydroCalculator:
|
712 |
+
def __init__(self, volume_liters=1.0):
|
713 |
+
self.volume = volume_liters
|
714 |
+
self.fertilizers = []
|
715 |
+
|
716 |
+
def add_fertilizer(self, name, grams):
|
717 |
+
if name not in fertilizers_db:
|
718 |
+
raise ValueError(f"Удобрение '{name}' не найдено в базе!")
|
719 |
+
self.fertilizers.append((name, grams))
|
720 |
+
|
721 |
+
def calculate_ppm(self):
|
722 |
+
ppm = {}
|
723 |
+
for name, grams in self.fertilizers:
|
724 |
+
for element, ratio in fertilizers_db[name].items():
|
725 |
+
ppm[element] = ppm.get(element, 0) + (grams * ratio * 1000) / self.volume
|
726 |
+
return ppm
|
727 |
+
|
728 |
+
def calculate_ec(self):
|
729 |
+
"""Расчёт EC по упрощённым коэффициентам"""
|
730 |
+
ppm = self.calculate_ppm()
|
731 |
+
ec = 0.0
|
732 |
+
|
733 |
+
EC_COEFFICIENTS = {
|
734 |
+
'N (NO3-)': 0.6,
|
735 |
+
'N (NH4+)': 0.4,
|
736 |
+
'K': 0.7,
|
737 |
+
'Ca': 0.75,
|
738 |
+
'Mg': 0.6,
|
739 |
+
'S': 0.3,
|
740 |
+
'P': 0.1,
|
741 |
+
}
|
742 |
+
|
743 |
+
for element, value in ppm.items():
|
744 |
+
if element in EC_COEFFICIENTS:
|
745 |
+
ec += value * EC_COEFFICIENTS[element]
|
746 |
+
|
747 |
+
return ec / 1000 # Переводим в mS/cm
|
748 |
+
|
749 |
+
def calculate_ec_exact(self):
|
750 |
+
"""Точный расчёт EC по молярной проводимости"""
|
751 |
+
# Молярные массы (г/моль)
|
752 |
+
MOLAR_MASSES = {
|
753 |
+
'NO3-': 62.0,
|
754 |
+
'NH4+': 18.0,
|
755 |
+
'K': 39.1,
|
756 |
+
'Ca': 40.1,
|
757 |
+
'Mg': 24.3,
|
758 |
+
'SO4--': 96.1,
|
759 |
+
'H2PO4-': 97.0,
|
760 |
+
}
|
761 |
+
|
762 |
+
# Молярная проводимость (λ₀) в мкСм·см²/моль
|
763 |
+
ION_CONDUCTIVITY = {
|
764 |
+
'NO3-': 71.4,
|
765 |
+
'NH4+': 73.5,
|
766 |
+
'K': 73.5,
|
767 |
+
'Ca': 119.0,
|
768 |
+
'Mg': 106.0,
|
769 |
+
'SO4--': 160.0,
|
770 |
+
'H2PO4-': 33.0,
|
771 |
+
}
|
772 |
+
|
773 |
+
# Соответствие между элементами в базе и ионами
|
774 |
+
ELEMENT_TO_ION = {
|
775 |
+
'N (NO3-)': 'NO3-',
|
776 |
+
'N (NH4+)': 'NH4+',
|
777 |
+
'K': 'K',
|
778 |
+
'Ca': 'Ca',
|
779 |
+
'Mg': 'Mg',
|
780 |
+
'S': 'SO4--',
|
781 |
+
'P': 'H2PO4-',
|
782 |
+
}
|
783 |
+
|
784 |
+
ppm = self.calculate_ppm()
|
785 |
+
ec = 0.0 # мкСм/см
|
786 |
+
|
787 |
+
for element, value in ppm.items():
|
788 |
+
if element in ELEMENT_TO_ION:
|
789 |
+
ion = ELEMENT_TO_ION[element]
|
790 |
+
molarity = value / (MOLAR_MASSES[ion] * 1000) # ppm → моль/л
|
791 |
+
ec += molarity * ION_CONDUCTIVITY[ion]
|
792 |
+
|
793 |
+
return ec / 1000 # Переводим в mS/cm
|
794 |
|
795 |
+
def print_report(self):
|
796 |
+
ppm = self.calculate_ppm()
|
797 |
+
ec_simple = self.calculate_ec()
|
798 |
+
ec_exact = self.calculate_ec_exact()
|
799 |
+
|
800 |
+
print("\nРезультаты расчёта:")
|
801 |
+
print("-" * 50)
|
802 |
+
print("{:<15} {:>10} {:>15}".format("Элемент", "ppm", "мг/л"))
|
803 |
+
print("-" * 50)
|
804 |
+
for element, value in sorted(ppm.items()):
|
805 |
+
print("{:<15} {:>10.2f} {:>15.2f}".format(element, value, value))
|
806 |
+
print("-" * 50)
|
807 |
+
print("Электропроводность:")
|
808 |
+
print(f"Упрощённый метод: {ec_simple:.2f} mS/cm")
|
809 |
+
print(f"Точный метод: {ec_exact:.2f} mS/cm")
|
810 |
+
print("-" * 50)
|
811 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
812 |
|
813 |
|
814 |
|
815 |
|
816 |
+
calc = HydroCalculator(10) # 10 литров раствора
|
817 |
+
calc.add_fertilizer("Кальциевая селитра", 100) # 100 г
|
818 |
+
calc.add_fertilizer("Сульфат магния", 50) # 50 г
|
819 |
+
calc.add_fertilizer("Монофосфат калия", 30) # 30 г
|
820 |
|
|
|
|
|
|
|
|
|
|
|
821 |
calc.print_report()
|
822 |
|
823 |
|
|
|
827 |
|
828 |
|
829 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
830 |
|
831 |
|
832 |
|