## 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 . ## -*- texinfo -*- ## @deftypefn {} {@var{retval} =} water_optimizer (@var{input1}, @var{input2}) ## ## @seealso{} ## @end deftypefn ## Author: Jens ## Created: 2023-06-08 function water_optimizer (TEST_SUITE, k_ve, learning_rate) # Load constants water_constants() # Profile from tap water 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 # Target Profile k_Ca_1_mg = 50; % mg/l k_Mg_1_mg = 20; % mg/l k_Na_1_mg = 20; % mg/l k_Cl_1_mg = 100; % mg/l k_S_1_mg = 50; % mg/l # Create common used compounds M_CaSO4 = create_mol([i_Ca i_S i_O], [1 1 4], mol_masses) M_CaCl2 = create_mol([i_Ca i_Cl], [1 2], mol_masses) M_NaCl = create_mol([i_Na i_Cl], [1 1], mol_masses) M_MgSO4 = create_mol([i_Mg i_S i_O], [1 1 4], mol_masses) M_NaHCO3 = create_mol([i_Na i_H i_C i_O], [1 1 1 3], mol_masses) M_HCl = create_mol([i_H i_Cl], [1 1], mol_masses) # Create single elements M_EL_Ca = create_mol([i_Ca], [1], mol_masses) M_EL_Mg = create_mol([i_Mg], [1], mol_masses) M_EL_Na = create_mol([i_Na], [1], mol_masses) M_EL_Cl = create_mol([i_Cl], [1], mol_masses) M_EL_S = create_mol([i_S], [1], mol_masses) # Initial profile M_Ca_0_mmol = k_Ca_0_mg/M_Ca; % mmol/l M_Mg_0_mmol = k_Mg_0_mg/M_Mg; % mmol/l M_Na_0_mmol = k_Na_0_mg/M_Na; % mmol/l M_Cl_0_mmol = k_Cl_0_mg/M_Cl; % mmol/l M_S_0_mmol = k_S_0_mg/M_S; % mmol/l A0 = k_ve*create_mol([i_Ca i_Mg i_Na i_Cl i_S], [M_Ca_0_mmol M_Mg_0_mmol M_Na_0_mmol M_Cl_0_mmol M_S_0_mmol], mol_masses) # Target profile M_Ca_1_mmol = k_Ca_1_mg/M_Ca; % mmol/l M_Mg_1_mmol = k_Mg_1_mg/M_Mg; % mmol/l M_Na_1_mmol = k_Na_1_mg/M_Na; % mmol/l M_Cl_1_mmol = k_Cl_1_mg/M_Cl; % mmol/l M_S_1_mmol = k_S_1_mg/M_S; % mmol/l T = create_mol([i_Ca i_Mg i_Na i_Cl i_S], [M_Ca_1_mmol M_Mg_1_mmol M_Na_1_mmol M_Cl_1_mmol M_S_1_mmol], mol_masses) if TEST_SUITE == 1, # Allowed substances, easy Pp = [M_EL_Ca; M_EL_Mg; M_EL_Na; M_EL_Cl; M_EL_S]; end if TEST_SUITE == 2, # Allowed substances, difficult Pp = [M_CaSO4; M_CaCl2; M_MgSO4; M_NaCl; M_HCl]; end # Init vecfit vars [N_subst, N_elem] = size(Pp); Pa = 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; V = 50; % liter _dn = []; CONV_COUNTER_RELOAD = 20; Dn0 = 1; conv_counter = CONV_COUNTER_RELOAD; while true, [A1, Pa, Dn1] = vecfit(Pp,mask,T,A0,Pa, 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") A1=A1 Dn1 = Dn1 Pa=Pa endfunction function zr = round_n(z, n) zr = round(z*10^n)/10^n; endfunction