Skip to content

Commit 653e7e5

Browse files
committed
New switching logics due to changes in SE
1 parent d027c81 commit 653e7e5

File tree

4 files changed

+218
-36
lines changed

4 files changed

+218
-36
lines changed

pySDC/implementations/problem_classes/Battery.py

Lines changed: 120 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=imex_mesh):
4040

4141
self.A = np.zeros((2, 2))
4242
self.t_switch = None
43+
self.count_switches = 0
4344

4445
def eval_f(self, u, t):
4546
"""
@@ -54,11 +55,21 @@ def eval_f(self, u, t):
5455
f = self.dtype_f(self.init, val=0.0)
5556
f.impl[:] = self.A.dot(u)
5657

57-
if t >= self.t_switch if self.t_switch is not None else u[1] <= self.params.V_ref:
58-
f.expl[0] = self.params.Vs / self.params.L
58+
if self.t_switch is not None:
59+
if t >= self.t_switch:
60+
f.expl[0] = self.params.Vs / self.params.L
61+
print('Vs')
62+
else:
63+
f.expl[0] = 0
64+
print('C1')
5965

6066
else:
61-
f.expl[0] = 0
67+
if u[1] <= self.params.V_ref:
68+
f.expl[0] = self.params.Vs / self.params.L
69+
print("Vs")
70+
else:
71+
f.expl[0] = 0
72+
print("C1")
6273

6374
return f
6475

@@ -75,11 +86,17 @@ def solve_system(self, rhs, factor, u0, t):
7586
"""
7687
self.A = np.zeros((2, 2))
7788

78-
if t >= self.t_switch if self.t_switch is not None else rhs[1] <= self.params.V_ref:
79-
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
89+
if self.t_switch is not None:
90+
if t >= self.t_switch:
91+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
92+
else:
93+
self.A[1, 1] = -1 / (self.params.C * self.params.R)
8094

8195
else:
82-
self.A[1, 1] = -1 / (self.params.C * self.params.R)
96+
if rhs[1] <= self.params.V_ref:
97+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
98+
else:
99+
self.A[1, 1] = -1 / (self.params.C * self.params.R)
83100

84101
me = self.dtype_u(self.init)
85102
me[:] = np.linalg.solve(np.eye(self.params.nvars) - factor * self.A, rhs)
@@ -102,6 +119,41 @@ def u_exact(self, t):
102119

103120
return me
104121

122+
def get_switching_info(self, u, t):
123+
"""
124+
Provides information about a discrete event for one subinterval.
125+
Args:
126+
u (dtype_u): current values
127+
t (float): current time
128+
Returns:
129+
switch_detected (bool): Indicates if a switch is found or not
130+
m_guess (np.int): Index of where the discrete event would found
131+
vC_switch (list): Contains function values of switching condition (for interpolation)
132+
"""
133+
134+
switch_detected = False
135+
m_guess = -100
136+
137+
for m in range(len(u)):
138+
if u[m][1] - self.params.V_ref <= 0:
139+
switch_detected = True
140+
m_guess = m - 1
141+
break
142+
143+
vC_switch = []
144+
if switch_detected:
145+
for m in range(1, len(u)):
146+
vC_switch.append(u[m][1] - self.params.V_ref)
147+
148+
return switch_detected, m_guess, vC_switch
149+
150+
def set_counter(self):
151+
"""
152+
Counts the number of switches found.
153+
"""
154+
155+
self.count_switches += 1
156+
105157

106158
class battery_implicit(ptype):
107159
"""
@@ -148,6 +200,7 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=mesh):
148200

149201
self.A = np.zeros((2, 2))
150202
self.t_switch = None
203+
self.count_switches = 0
151204
self.newton_itercount = 0
152205
self.lin_itercount = 0
153206
self.newton_ncalls = 0
@@ -166,13 +219,21 @@ def eval_f(self, u, t):
166219
f = self.dtype_f(self.init, val=0.0)
167220
non_f = np.zeros(2)
168221

169-
if t >= self.t_switch if self.t_switch is not None else u[1] <= self.params.V_ref:
170-
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
171-
non_f[0] = self.params.Vs / self.params.L
222+
if self.t_switch is not None:
223+
if t >= self.t_switch:
224+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
225+
non_f[0] = self.params.Vs / self.params.L
226+
else:
227+
self.A[1, 1] = -1 / (self.params.C * self.params.R)
228+
non_f[0] = 0
172229

173230
else:
174-
self.A[1, 1] = -1 / (self.params.C * self.params.R)
175-
non_f[0] = 0
231+
if u[1] <= self.params.V_ref:
232+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
233+
non_f[0] = self.params.Vs / self.params.L
234+
else:
235+
self.A[1, 1] = -1 / (self.params.C * self.params.R)
236+
non_f[0] = 0
176237

177238
f[:] = self.A.dot(u) + non_f
178239

@@ -194,13 +255,21 @@ def solve_system(self, rhs, factor, u0, t):
194255
non_f = np.zeros(2)
195256
self.A = np.zeros((2, 2))
196257

197-
if t >= self.t_switch if self.t_switch is not None else rhs[1] <= self.params.V_ref:
198-
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
199-
non_f[0] = self.params.Vs / self.params.L
258+
if self.t_switch is not None:
259+
if t >= self.t_switch:
260+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
261+
non_f[0] = self.params.Vs / self.params.L
262+
else:
263+
self.A[1, 1] = -1 / (self.params.C * self.params.R)
264+
non_f[0] = 0
200265

201266
else:
202-
self.A[1, 1] = -1 / (self.params.C * self.params.R)
203-
non_f[0] = 0
267+
if rhs[1] <= self.params.V_ref:
268+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
269+
non_f[0] = self.params.Vs / self.params.L
270+
else:
271+
self.A[1, 1] = -1 / (self.params.C * self.params.R)
272+
non_f[0] = 0
204273

205274
# start newton iteration
206275
n = 0
@@ -256,3 +325,38 @@ def u_exact(self, t):
256325
me[1] = self.params.alpha * self.params.V_ref # vC
257326

258327
return me
328+
329+
def get_switching_info(self, u, t):
330+
"""
331+
Provides information about a discrete event for one subinterval.
332+
Args:
333+
u (dtype_u): current values
334+
t (float): current time
335+
Returns:
336+
switch_detected (bool): Indicates if a switch is found or not
337+
m_guess (np.int): Index of where the discrete event would found
338+
vC_switch (list): Contains function values of switching condition (for interpolation)
339+
"""
340+
341+
switch_detected = False
342+
m_guess = -100
343+
344+
for m in range(len(u)):
345+
if u[m][1] - self.params.V_ref <= 0:
346+
switch_detected = True
347+
m_guess = m - 1
348+
break
349+
350+
vC_switch = []
351+
if switch_detected:
352+
for m in range(1, len(u)):
353+
vC_switch.append(u[m][1] - self.params.V_ref)
354+
355+
return switch_detected, m_guess, vC_switch
356+
357+
def set_counter(self):
358+
"""
359+
Counts the number of switches found.
360+
"""
361+
362+
self.count_switches += 1

pySDC/implementations/problem_classes/Battery_2Condensators.py

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ def __init__(self, problem_params, dtype_u=mesh, dtype_f=imex_mesh):
4141
)
4242

4343
self.A = np.zeros((3, 3))
44+
self.SV = 0
45+
self.SC1 = 1
46+
self.SC2 = 0
4447
self.t_switch = None
48+
self.count_switches = 0
49+
self.diff = 0.0
4550

4651
def eval_f(self, u, t):
4752
"""
@@ -57,15 +62,29 @@ def eval_f(self, u, t):
5762
f.impl[:] = self.A.dot(u)
5863

5964
if u[2] > self.params.V_ref[1]:
60-
if t >= self.t_switch if self.t_switch is not None else u[1] <= self.params.V_ref[0]:
61-
# switch to C2
62-
f.expl[0] = 0
63-
64-
elif u[1] > self.params.V_ref[0]:
65-
# C1 supplies energy
66-
f.expl[0] = 0
67-
68-
elif t >= self.t_switch if self.t_switch is not None else u[2] <= self.params.V_ref[1]:
65+
if self.t_switch is not None:
66+
if t >= self.t_switch:
67+
if self.count_switches == 1:
68+
# switch to C2
69+
f.expl[0] = 0
70+
elif self.count_switches == 2:
71+
# switch to Vs
72+
f.expl[0] = self.params.Vs / self.params.L
73+
else:
74+
if self.count_switches == 1:
75+
# C1 supplies energy
76+
f.expl[0] = 0
77+
elif self.count_switches == 2:
78+
# C2 supplies energy
79+
f.expl[0] = 0
80+
else:
81+
if u[1] > self.params.V_ref[0]:
82+
# C1 supplies energy
83+
f.expl[0] = 0
84+
else:
85+
# switch to C2
86+
f.expl[0] = 0
87+
else:
6988
# switch to Vs
7089
f.expl[0] = self.params.Vs / self.params.L
7190

@@ -85,15 +104,33 @@ def solve_system(self, rhs, factor, u0, t):
85104
self.A = np.zeros((3, 3))
86105

87106
if rhs[2] > self.params.V_ref[1]:
88-
if t >= self.t_switch if self.t_switch is not None else rhs[1] <= self.params.V_ref[0]:
89-
# switch to C2
90-
self.A[2, 2] = -1 / (self.params.C2 * self.params.R)
91-
92-
elif rhs[1] > self.params.V_ref[0]:
93-
# C1 supplies energy
94-
self.A[1, 1] = -1 / (self.params.C1 * self.params.R)
95-
96-
elif t >= self.t_switch if self.t_switch is not None else rhs[2] <= self.params.V_ref[1]:
107+
if self.t_switch is not None:
108+
if t >= self.t_switch:
109+
if self.count_switches == 1:
110+
# switch to C2
111+
self.A[2, 2] = -1 / (self.params.C2 * self.params.R)
112+
elif self.count_switches == 2:
113+
# switch to Vs
114+
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
115+
116+
else:
117+
if self.count_switches == 1:
118+
# C1 supplies energy
119+
self.A[1, 1] = -1 / (self.params.C1 * self.params.R)
120+
elif self.count_switches == 2:
121+
# C2 supplies energy
122+
self.A[2, 2] = -1 / (self.params.C2 * self.params.R)
123+
124+
else:
125+
if rhs[1] > self.params.V_ref[0]:
126+
# C1 supplies energy
127+
self.A[1, 1] = -1 / (self.params.C1 * self.params.R)
128+
129+
else:
130+
# switch to C2
131+
self.A[2, 2] = -1 / (self.params.C2 * self.params.R)
132+
133+
else:
97134
# switch to Vs
98135
self.A[0, 0] = -(self.params.Rs + self.params.R) / self.params.L
99136

@@ -117,3 +154,44 @@ def u_exact(self, t):
117154
me[1] = self.params.alpha * self.params.V_ref[0] # vC1
118155
me[2] = self.params.alpha * self.params.V_ref[1] # vC2
119156
return me
157+
158+
def get_switching_info(self, u, t):
159+
"""
160+
Provides information about a discrete event for one subinterval.
161+
Args:
162+
u (dtype_u): current values
163+
t (float): current time
164+
Returns:
165+
switch_detected (bool): Indicates if a switch is found or not
166+
m_guess (np.int): Index of where the discrete event would found
167+
vC_switch (list): Contains function values of switching condition (for interpolation)
168+
"""
169+
170+
switch_detected = False
171+
m_guess = -100
172+
173+
for m in range(len(u)):
174+
for k in range(1, self.params.nvars):
175+
if u[m][k] - self.params.V_ref[k - 1] <= 0:
176+
switch_detected = True
177+
m_guess = m - 1
178+
k_detected = k
179+
break
180+
181+
if k == self.params.nvars and switch_detected and u[m][k] - self.params.V_ref[k - 1] <= 0:
182+
msg = 'A discrete event is already found! Multiple switching handling in the same interval is not yet implemented!'
183+
raise AssertionError(msg)
184+
185+
vC_switch = []
186+
if switch_detected:
187+
for m in range(1, len(u)):
188+
vC_switch.append(u[m][k_detected] - self.params.V_ref[k_detected - 1])
189+
190+
return switch_detected, m_guess, vC_switch
191+
192+
def set_counter(self):
193+
"""
194+
Counts the number of switches found.
195+
"""
196+
197+
self.count_switches += 1

pySDC/projects/PinTSimE/battery_2condensators_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def main(use_switch_estimator=True):
9494

9595
# initialize step parameters
9696
step_params = dict()
97-
step_params['maxiter'] = 5
97+
step_params['maxiter'] = 4
9898

9999
# initialize controller parameters
100100
controller_params = dict()

pySDC/projects/PinTSimE/battery_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ def run():
183183
problem_classes = [battery, battery_implicit]
184184
sweeper_classes = [imex_1st_order, generic_implicit]
185185
use_switch_estimator = [True]
186-
use_adaptivity = [False]
186+
use_adaptivity = [True]
187187

188188
for problem, sweeper in zip(problem_classes, sweeper_classes):
189189
for use_SE in use_switch_estimator:

0 commit comments

Comments
 (0)