Skip to content

Add new tutorial: resonant circuit tutorial #480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 25 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c3fb660
Copy content from https://github.com/precice/matlab-bindings/tree/2e9…
BenjaminRodenberg Mar 14, 2024
023afb4
Example modified according to correct structure of tutorials
NiklasVin Mar 20, 2024
3fe567b
Renamed Solver files and variables
NiklasVin Mar 23, 2024
06a7688
fixed pipeline issue in matlab-binding-path.sh
NiklasVin Mar 23, 2024
0c2a0ca
Merge branch 'develop' into add-lc-circuit
BenjaminRodenberg Mar 25, 2024
4c89b36
Merge branch 'add-lc-circuit' of github.com:BenjaminRodenberg/tutoria…
BenjaminRodenberg Mar 25, 2024
6de181b
Fixed shellcheck warning
NiklasVin Mar 26, 2024
21eb24f
Clean up config file
NiklasVin Mar 26, 2024
e3d3df0
Merge remote-tracking branch 'origin/add-lc-circuit' into add-lc-circuit
NiklasVin Mar 27, 2024
37bf738
Remove non-existent image
NiklasVin Mar 27, 2024
e5de61c
preCICE config file formatted, README error fixed
NiklasVin Apr 8, 2024
0819c23
Ignore MATLAB files with formatting.
BenjaminRodenberg Apr 16, 2024
b02ec5d
Rename.
BenjaminRodenberg Apr 16, 2024
75a82f3
Fix formatting
BenjaminRodenberg Apr 16, 2024
815b4b5
Suggested renaming of meshes
NiklasVin Apr 18, 2024
ea4fab5
Added clean_matlab() to cleaning-tools, modified clean files & simpli…
NiklasVin Apr 18, 2024
5063edf
Merge branch 'precice:develop' into add-lc-circuit
NiklasVin Apr 18, 2024
74c503f
Add precice configuration image to README
NiklasVin Apr 18, 2024
4dfefd7
Fix format.
BenjaminRodenberg Apr 19, 2024
ae37470
delete blank line
NiklasVin Apr 19, 2024
ffbac07
Update resonant-circuit/README.md
BenjaminRodenberg Apr 19, 2024
b877856
Update resonant-circuit/README.md
BenjaminRodenberg Apr 19, 2024
ecfb95e
Add example plot and applied suggested changes in README file
NiklasVin Apr 24, 2024
e20217c
Merge branch 'develop' into add-lc-circuit
BenjaminRodenberg Apr 24, 2024
4697279
Add changelog.
BenjaminRodenberg Apr 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ repos:
rev: 'v14.0.6'
hooks:
- id: clang-format
exclude: '\.json$'
exclude: '\.(json|m|mm)$'
- repo: https://github.com/koalaman/shellcheck-precommit
rev: v0.10.0
hooks:
Expand Down
1 change: 1 addition & 0 deletions changelog-entries/480.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Added new [resonant-circuit tutorial](https://precice.org/tutorials-resonant-circuit.html) with MATLAB (migrated from [matlab-bindings repository](https://github.com/precice/matlab-bindings and updated to follow tutorials structure)).
75 changes: 75 additions & 0 deletions resonant-circuit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
---
title: Resonant Circuit
keywords: MATLAB
summary: We simulate a two-element LC circuit (one inductor and one capacitor).
---


## Setup

The purpose of this tutorial is to illustrate the usage of preCICE to couple MATLAB code. Two different MATLAB solvers will be coupled to simulate a two-element LC circuit. This type of circuit consists on a very simple system with one inductor and one capacitor:

![LC circuit diagram [1]](images/tutorials-resonant-circuit-diagram.svg)

The circuit is described by the following system of ODEs:

$U(t) = L \frac{\text{d}I}{\text{d}t}$

$I(t) = -C \frac{\text{d}U}{\text{d}t}$

where $I$ is the current and $U$ the voltage of the cirucit.

Each of these equations is going to be solved by a different MATLAB solver. Note that as only one scalar is solved per equation, this is a 0+1 dimensional problem.

## Configuration

preCICE configuration (image generated using the [precice-config-visualizer](https://precice.org/tooling-config-visualization.html)):

![preCICE configuration visualization](images/tutorials-resonant-circuit-precice-config.png)

## Available solvers

* *MATLAB* A solver using the [MATLAB bindings](https://precice.org/installation-bindings-matlab.html).
Before running this tutorial, follow the [instructions](https://precice.org/installation-bindings-matlab.html) to correctly install the MATLAB bindings.

## Running the simulation

### MATLAB

For running this example, first get into one of folders with the solvers and open a MATLAB instance.
Afterward, do the same for the second solver.
After adding the MATLAB bindings to the MATLAB path (in both instances), run the following commands:

In the first MATLAB instance one can run the solver for the current:

```MATLAB
coil
```

And in the second MATLAB instance the solver for the voltage:

```MATLAB
capacitor
```

The preCICE configuration file is available as `precice-config.xml`, and it is called directly in the solvers.

#### Running from terminal

If you prefer to not open the MATLAB GUIs, you can alternatively use two shells instead.
For that, modify the path in the file `matlab-bindings-path.sh` found in the base directory of this tutorial to the path to your MATLAB bindings.

By doing that, you can now open two shells and switch into the directories `capacitor-matlab` and `coil-matlab` and execute the `run.sh` scripts.

## Post-processing

The solver for the current also records the current and voltage through time and at the end of the simulation saves a plot with the obtained curves, as well as the analytical solution.

After successfully running the coupling, one can find the curves in the folder `capacitor-matlab` as `Curves.png`.

The `Curves.png` plot could exemplarily look like the following:
![Voltage and current plot of the resonant circuit](images/tutorials-resonant-circuit-curves.png)

## References

[1] Schematic of a simple parallel LC circuit by First Harmonic - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=21991221
106 changes: 106 additions & 0 deletions resonant-circuit/capacitor-matlab/capacitor.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
clear; close all; clc;

% Initialize and configure preCICE
interface = precice.Participant("Capacitor", "../precice-config.xml", 0, 1);

% Geometry IDs. As it is a 0-D simulation, only one vertex is necessary.
meshName ="Capacitor-Mesh";
vertex_ID = interface.setMeshVertex(meshName, [0 0]);

% Data IDs
dataNameI = "Current";
dataNameU = "Voltage";

% Simulation parameters and initial condition
C = 2; % Capacitance
L = 1; % Inductance
t0 = 0; % Initial simulation time
t_max = 10; % End simulation time
Io = 1; % Initial voltage
phi = 0; % Phase of the signal

w0 = 1/sqrt(L*C); % Resonant frequency
I0 = Io*cos(phi); % Initial condition for I
U0 = -w0*L*Io*sin(phi); % Initial condition for U

f_U = @(t, U, I) -I/C; % Time derivative of U

% Initialize simulation
if interface.requiresInitialData()
interface.writeData(meshName, DataNameU, vertex_ID, U0);
end
interface.initialize();
dt = interface.getMaxTimeStepSize();

I = I0; % Vector of I through time
U = U0; % Vector of U through time
t_vec = t0; % Vector of time


% Start simulation
t = t0 + dt;
while interface.isCouplingOngoing()

% Record checkpoint if necessary
if interface.requiresWritingCheckpoint()
I0_checkpoint = I0;
U0_checkpoint = U0;
end

% Make Simulation Step
[t_ode, U_ode] = ode45(@(t, y) f_U(t, y, I0), [t0 t], U0);
U0 = U_ode(end);

% Exchange data
interface.writeData(meshName, dataNameU, vertex_ID, U0);
interface.advance(dt);

% Recover checkpoint if not converged, else finish time step
if interface.requiresReadingCheckpoint()
I0 = I0_checkpoint;
U0 = U0_checkpoint;
else
dt = interface.getMaxTimeStepSize();
I0 = interface.readData(meshName, dataNameI, vertex_ID, dt);
U = [U U0];
I = [I I0];
t_vec = [t_vec, t];
t0 = t;
t = t0 + dt;
end

end

% Stop coupling
interface.finalize();
% Analytical solution for comparison
I_an = Io*cos(w0*t_vec+phi);
U_an = -w0*L*Io*sin(w0*t_vec+phi);

% print maximal error over the whole time interval for the voltage and the
% current
error_I = max(abs(I_an-I));
error_U = max(abs(U_an-U));
fprintf('Error in I: %d \n', error_I);
fprintf('Error in U: %d \n', error_U);

% Make and save plot
figure(1)
subplot(2,1,1)
plot(t_vec, I_an)
hold on;
plot(t_vec, U_an)
ylim([-1,1])
legend('I', 'U')
title('Analytical')

subplot(2,1,2)
plot(t_vec, I)
hold on;
plot(t_vec, U)
ylim([-1,1])
title('Numerical')
legend('I', 'U')

save('outputs.mat', 'I', 'U')
saveas(gcf, 'Curves.png')
8 changes: 8 additions & 0 deletions resonant-circuit/capacitor-matlab/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh
set -e -u

rm ./*.png ./*.mat

. ../../tools/cleaning-tools.sh

clean_matlab .
4 changes: 4 additions & 0 deletions resonant-circuit/capacitor-matlab/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

# Run MATLAB code without GUI
matlab -nodisplay -r "capacitor;exit;"
1 change: 1 addition & 0 deletions resonant-circuit/clean-tutorial.sh
6 changes: 6 additions & 0 deletions resonant-circuit/coil-matlab/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/sh
set -e -u

. ../../tools/cleaning-tools.sh

clean_matlab .
68 changes: 68 additions & 0 deletions resonant-circuit/coil-matlab/coil.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
clear; close all; clc;

% Initialize and configure preCICE
interface = precice.Participant("Coil", "../precice-config.xml", 0, 1);

% Geometry IDs. As it is a 0-D simulation, only one vertex is necessary.
meshName ="Coil-Mesh";
vertex_ID = interface.setMeshVertex(meshName, [0 0]);

% Data IDs
dataNameI = "Current";
dataNameU = "Voltage";

% Simulation parameters and initial condition
L = 1; % Inductance
t0 = 0; % Initial simulation time
t_max = 10; % End simulation time
Io = 1; % Initial voltage
phi = 0; % Phase of the signal

I0 = Io*cos(phi); % Initial condition for I

f_I = @(t, I, U) U/L; % Time derivative of I

if interface.requiresInitialData()
interface.writeData(meshName, DataNameI, vertex_ID, I0);
end
interface.initialize();
dt = interface.getMaxTimeStepSize();

% Initialize simulation
U0 = interface.readData(meshName, dataNameU, vertex_ID, 0); % Initial voltage
t_vec = t0; % Vector of time


% Start simulation
t = t0 + dt;
while interface.isCouplingOngoing()

% Record checkpoint if necessary
if interface.requiresWritingCheckpoint()
I0_checkpoint = I0;
U0_checkpoint = U0;
end

% Make Simulation Step
[t_ode, I_ode] = ode45(@(t, y) f_I(t, y, U0), [t0 t], I0);
I0 = I_ode(end);

% Exchange data
interface.writeData(meshName, dataNameI, vertex_ID, I0);
interface.advance(dt);

% Recover checkpoint if not converged, else finish time step
if interface.requiresReadingCheckpoint()
I0 = I0_checkpoint;
U0 = U0_checkpoint;
else
dt = interface.getMaxTimeStepSize();
U0 = interface.readData(meshName, dataNameU, vertex_ID, dt);
t0 = t;
t = t0 + dt;
end

end

% Stop coupling
interface.finalize();
4 changes: 4 additions & 0 deletions resonant-circuit/coil-matlab/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh

# Run MATLAB code without GUI
matlab -nodisplay -r "coil;exit;"
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions resonant-circuit/images/tutorials-resonant-circuit-diagram.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions resonant-circuit/precice-config.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<precice-configuration>
<data:scalar name="Current" />
<data:scalar name="Voltage" />

<mesh name="Coil-Mesh" dimensions="2">
<use-data name="Current" />
<use-data name="Voltage" />
</mesh>

<mesh name="Capacitor-Mesh" dimensions="2">
<use-data name="Current" />
<use-data name="Voltage" />
</mesh>

<participant name="Coil">
<provide-mesh name="Coil-Mesh" />
<write-data name="Current" mesh="Coil-Mesh" />
<read-data name="Voltage" mesh="Coil-Mesh" />
</participant>

<participant name="Capacitor">
<provide-mesh name="Capacitor-Mesh" />
<receive-mesh name="Coil-Mesh" from="Coil" />
<write-data name="Voltage" mesh="Capacitor-Mesh" />
<read-data name="Current" mesh="Capacitor-Mesh" />
<mapping:nearest-neighbor
direction="write"
from="Capacitor-Mesh"
to="Coil-Mesh"
constraint="consistent" />
<mapping:nearest-neighbor
direction="read"
from="Coil-Mesh"
to="Capacitor-Mesh"
constraint="consistent" />
</participant>

<m2n:sockets acceptor="Coil" connector="Capacitor" exchange-directory=".." />

<coupling-scheme:serial-implicit>
<participants first="Coil" second="Capacitor" />
<max-time value="10" />
<time-window-size value="0.01" />
<max-iterations value="3" />
<exchange data="Current" mesh="Coil-Mesh" from="Coil" to="Capacitor" />
<exchange data="Voltage" mesh="Coil-Mesh" from="Capacitor" to="Coil" />
</coupling-scheme:serial-implicit>
</precice-configuration>
Loading
Loading