|
1 | 1 | import pandas as pd |
2 | 2 | import json |
| 3 | +import numpy as np |
| 4 | +from scipy.integrate import solve_ivp #solve odes |
3 | 5 | from DataModels.input_definition import InputKeys |
| 6 | +from DataModels.model_definition import ModelKeys |
| 7 | +from Nebenrechnungen import Nebenrechnungen |
| 8 | +from Fx_ODE_Bioreaktor import Bioreaktor_ODE #hier wird das Differentialgleichungssystem definiert |
4 | 9 |
|
5 | 10 | MODEL_PATH = "./src/DataModels/model_db.json" |
6 | 11 |
|
7 | 12 |
|
8 | | -def calculate(df: pd.DataFrame) -> pd.DataFrame: |
| 13 | +def calculate(ferm_param_in_df: pd.DataFrame) -> pd.DataFrame: |
9 | 14 | try: |
10 | | - model_name = df[InputKeys.model][0] |
| 15 | + model_number = int(ferm_param_in_df[InputKeys.model][0]-1) #"-1" as indices start with 0 and model numbers start with 1 |
| 16 | + print("Genutztes Model hat die Nummer: ", model_number+1) |
11 | 17 | with open(MODEL_PATH) as f: |
12 | 18 | model = json.load(f) |
13 | | - model = model[model_name] |
| 19 | + model_param_in= model[model_number] #dictionary |
| 20 | + #print (model_param_in[ModelKeys.YPS1]) |
14 | 21 |
|
15 | 22 | except json.JSONDecodeError: |
16 | 23 | print("Invalid JSON input.") |
17 | 24 | pass |
18 | 25 |
|
19 | | - result_df = pd.DataFrame([]) |
20 | | - |
21 | | - # nebenberechnung |
22 | | - # vorberechnung |
23 | | - |
| 26 | + # Nebenberechnung |
| 27 | + [model_param,ferm_param_df]=Nebenrechnungen(model_param_in,ferm_param_in_df) |
| 28 | + |
| 29 | + #global constants |
| 30 | + data_rate=60 #data rate per hour |
| 31 | + Vm_norm=22.41396954 #molares Volumen in NL/mol bei Normbedingungen (0°C und 101,325 kPa) |
| 32 | + c_O2_Luft = 0.2095 #Sauerstoffgehalt Luft in mol(O2)/mol(Luft) |
| 33 | + c_CO2_Luft =0.0004147 #CO2 Gehalt der Luft in mol(CO2)/mol(Luft) |
| 34 | + |
| 35 | + |
24 | 36 | # nachfolgend Hauptberechnung |
25 | | - for index, row in df.iterrows(): |
| 37 | + for index, row in ferm_param_df.iterrows(): |
26 | 38 | # result_df hier befüllen |
27 | | - pass |
| 39 | + print("Phase:", row[InputKeys.phase]) |
| 40 | + |
| 41 | + if index==0: |
| 42 | + c_x_0=row[InputKeys.c_x0] |
| 43 | + c_S1_0=row[InputKeys.bolus_c] |
| 44 | + c_S2_0=row[InputKeys.bolus_n] |
| 45 | + c_P_0=0 |
| 46 | + c_DO_0=row[InputKeys.c_o2_sat]*row[InputKeys.do]/100 |
| 47 | + |
| 48 | + y0=[c_x_0,c_S1_0,c_S2_0, c_P_0, c_DO_0, c_O2_Luft, c_CO2_Luft] #Startparameter in Vektor |
| 49 | + t_start=0 |
| 50 | + t_ende=row[InputKeys.duration] |
| 51 | + |
| 52 | + else: |
| 53 | + c_x_0=y[-1,0] #"-1" means the last element of the array |
| 54 | + c_S1_0=y[-1,1]+row[InputKeys.bolus_c] |
| 55 | + c_S2_0=y[-1,2]+row[InputKeys.bolus_n] |
| 56 | + c_P_0=y[-1,3] |
| 57 | + #print("c_P0",c_P_0) |
| 58 | + c_DO_0=y[-1,4] |
| 59 | + O2_Out=y[-1,5] #Konz. O2 in Abluft |
| 60 | + CO2_Out=y[-1,6] #Konz. CO2 in Abluft |
| 61 | + y0=[c_x_0,c_S1_0,c_S2_0, c_P_0, c_DO_0, O2_Out, CO2_Out] #Startparameter in Vektor |
| 62 | + t_start=result.t[-1] |
| 63 | + t_ende=t_start+row[InputKeys.duration] |
| 64 | + #print("Calc Phase: ",i," from ",t_start," - ",t_ende,"h") |
28 | 65 |
|
| 66 | + if row[InputKeys.duration]!=0: |
| 67 | + print("Calc Phase: ",index," from ",t_start," - ",t_ende,"h") |
| 68 | + datapoints=row[InputKeys.duration]*data_rate |
| 69 | + t_span=np.linspace(t_start,t_ende,datapoints) |
| 70 | + if datapoints < 50:datapoints=50 #this is needed in case a Phase is really short so the minimal number of datapoint per phase=50 |
| 71 | + Fpar_d=row.to_dict() #extract Fermentation parameters for current phase and convert to dictionary as this is faster in solve_ivp |
| 72 | + |
| 73 | + |
| 74 | + result=solve_ivp(Bioreaktor_ODE,(t_start,t_ende),y0,args=(model_param,Fpar_d), t_eval=t_span, max_step=0.0005, atol=1e-6, rtol=1e-7) |
| 75 | + #solve_IVP Explanations |
| 76 | + #args are passed as a tupel - a single element in a tupel is single_element_tuple = (5,) |
| 77 | + #via small atol and rtol practical "non-negative" is achieved |
| 78 | + # #Results of Solve_ivp stores y values in result.y which is an array of one row per parameter |
| 79 | + #and n-datapoints in n columns |
| 80 | + if index==0: |
| 81 | + y=result.y.T |
| 82 | + y_ges=y #transform array |
| 83 | + #print("dim y_ges", y_ges.shape) |
| 84 | + t_ges=np.atleast_2d(result.t).T |
| 85 | + #print("dim t_ges", t_ges.shape) |
| 86 | + # sum_feeding = t_span*Fpar["Feed_C"][0] |
| 87 | + # len_t_span=len(t_span) |
| 88 | + # Drehzahl = np.zeros(len_t_span)+Fpar["Drehzahl"][0] |
| 89 | + # Begasungsrate = np.zeros(len_t_span)+Fpar["Q_Air"][0] |
| 90 | + # Druck = np.zeros(len_t_span)+Fpar["Druck"][0] |
| 91 | + else: |
| 92 | + y=result.y.T #transform array |
| 93 | + y_ges=np.vstack((y_ges, y)) |
| 94 | + t=np.atleast_2d(result.t).T |
| 95 | + t_ges=np.vstack((t_ges, t)) |
| 96 | + # already_fed=sum_feeding[-1] |
| 97 | + # t_span_temp=np.subtract(t_span,t_span[0]) |
| 98 | + # temp_feed=already_fed+t_span_temp*Fpar["Feed_C"][i-1] |
| 99 | + # sum_feeding = np.hstack((sum_feeding, temp_feed)) |
| 100 | + # len_t_span=len(t_span) |
| 101 | + # Drehzahl = np.hstack((Drehzahl, np.zeros(len_t_span)+Fpar["Drehzahl"][i-1])) |
| 102 | + # Begasungsrate = np.hstack((Begasungsrate, np.zeros(len_t_span)+Fpar["Q_Air"][i-1])) |
| 103 | + # Druck = np.hstack((Druck,np.zeros(len_t_span)+Fpar["Druck"][i-1])) |
| 104 | + result_df=pd.DataFrame([0,0]) |
29 | 105 | return result_df |
0 commit comments