122 lines
3.1 KiB
Matlab
122 lines
3.1 KiB
Matlab
## Copyright (C) 2023 Jens
|
|
##
|
|
## This program is free software: you can redistribute it and/or modify
|
|
## it under the terms of the GNU General Public License as published by
|
|
## the Free Software Foundation, either version 3 of the License, or
|
|
## (at your option) any later version.
|
|
##
|
|
## This program is distributed in the hope that it will be useful,
|
|
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
## GNU General Public License for more details.
|
|
##
|
|
## You should have received a copy of the GNU General Public License
|
|
## along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
## -*- texinfo -*-
|
|
## @deftypefn {} {@var{retval} =} water_optimizer (@var{input1}, @var{input2})
|
|
##
|
|
## @seealso{}
|
|
## @end deftypefn
|
|
|
|
## Author: Jens <jens@orion>
|
|
## Created: 2023-06-08
|
|
|
|
function water_optimizer (TEST_SUITE, k_ve, learning_rate)
|
|
|
|
# Load constants
|
|
water_constants()
|
|
|
|
# Profile from tap water (Bad Toelz)
|
|
k_Ca_0_mg = 94.0; % mg/l
|
|
k_Mg_0_mg = 18.1; % mg/l
|
|
k_Na_0_mg = 3.6; % mg/l
|
|
k_S_0_mg = 44.1; % mg/l
|
|
k_Cl_0_mg = 4.6; % mg/l
|
|
k_HCO3_0_mmol = 5.5; % mmol/l
|
|
|
|
# Profile from tap water (Debug)
|
|
k_Ca_0_mg = 100; % mg/l
|
|
k_Mg_0_mg = 20; % mg/l
|
|
k_Na_0_mg = 5; % mg/l
|
|
k_S_0_mg = 50; % mg/l
|
|
k_Cl_0_mg = 5; % mg/l
|
|
|
|
# Target Profile
|
|
k_Ca_1_mg = 50; % mg/l
|
|
k_Mg_1_mg = 20; % mg/l
|
|
k_Na_1_mg = 40; % mg/l
|
|
k_Cl_1_mg = 100; % mg/l
|
|
k_S_1_mg = 50; % mg/l
|
|
|
|
# Tap water: Calc Stoffmenge/l [mmol/l]
|
|
n_Ca_0 = k_Ca_0_mg/sum(M_EL_Ca);
|
|
n_Mg_0 = k_Mg_0_mg/sum(M_EL_Mg);
|
|
n_Na_0 = k_Na_0_mg/sum(M_EL_Na);
|
|
n_Cl_0 = k_Cl_0_mg/sum(M_EL_Cl);
|
|
n_S_0 = k_S_0_mg/sum(M_EL_S);
|
|
|
|
# Target: Calc Stoffmenge/l [mmol/l]
|
|
n_Ca_1 = k_Ca_1_mg/sum(M_EL_Ca);
|
|
n_Mg_1 = k_Mg_1_mg/sum(M_EL_Mg);
|
|
n_Na_1 = k_Na_1_mg/sum(M_EL_Na);
|
|
n_Cl_1 = k_Cl_1_mg/sum(M_EL_Cl);
|
|
n_S_1 = k_S_1_mg/sum(M_EL_S);
|
|
|
|
# Initial profile
|
|
m_A0 = k_ve*create_mol([i_Ca i_Mg i_Na i_Cl i_S], [n_Ca_0 n_Mg_0 n_Na_0 n_Cl_0 n_S_0], mol_masses)
|
|
|
|
# Target profile
|
|
m_T = create_mol([i_Ca i_Mg i_Na i_Cl i_S], [n_Ca_1 n_Mg_1 n_Na_1 n_Cl_1 n_S_1], mol_masses)
|
|
|
|
if TEST_SUITE == 1,
|
|
# Create molar masses of allowed substances, easy
|
|
Mp = [M_EL_Ca; M_EL_Mg; M_EL_Na; M_EL_Cl; M_EL_S];
|
|
end
|
|
|
|
if TEST_SUITE == 2,
|
|
# Create molar masses of allowed substances, difficult
|
|
Mp = [M_CaSO4+2*M_H2O; M_CaCl2+2*M_H2O; M_MgSO4+7*M_H2O; M_NaCl; M_HCl]
|
|
end
|
|
|
|
# Init vecfit vars
|
|
[N_subst, N_elem] = size(Mp);
|
|
# create stoff mengen 'n' [mol]
|
|
na = zeros(N_subst, 1);
|
|
|
|
# ignore oxygen
|
|
mask = create_mol([i_Ca i_Mg i_S i_Cl i_Na], [1 1 1 1 1], mol_masses) > 0;
|
|
|
|
_dn = [];
|
|
CONV_COUNTER_RELOAD = 20;
|
|
Dn0 = 1;
|
|
conv_counter = CONV_COUNTER_RELOAD;
|
|
while true,
|
|
[m_A1, na, Dn1] = vecfit(Mp, mask, m_T, m_A0, na, learning_rate.*(1-exp(-Dn0)));
|
|
Dc = round_n(Dn1,2);
|
|
if Dn0 == Dc,
|
|
if conv_counter == 0,
|
|
break;
|
|
else
|
|
conv_counter -= 1;
|
|
end
|
|
else
|
|
conv_counter = CONV_COUNTER_RELOAD;
|
|
end
|
|
Dn0 = Dc;
|
|
_dn = [_dn Dn1];
|
|
end
|
|
plot(1:length(_dn), _dn); grid();
|
|
title("Distance"); xlabel("Iteration"); ylabel("Dn")
|
|
m_A1
|
|
Dn1
|
|
m_elem=sum(Mp.*na)
|
|
m_subst_add_g_per_hl = na.*sum(Mp,2)/1000*100
|
|
|
|
endfunction
|
|
|
|
function zr = round_n(z, n)
|
|
zr = round(z*10^n)/10^n;
|
|
endfunction
|
|
|