Skip to content

Commit 7d24f33

Browse files
simoniusranocha
authored andcommitted
A Dipole as a new example (#31)
* boundary conditions for MHD * applied requested changes * used a Macro instead of pow(..., 2) * Added speeds from Bouchut, Klingenberg and Waagan (2012) * proper handling of misdefined preprocessor symbols * clear distinction between a analytic soloution and the initial and boundary values, which is needed for a new example * Made some structural changes for the computation of the surface terms * changed the USE_VR_* to USE_HLL_SPEED_*, #ifndef USE_PERIODIC to #ifdef USE_BOUNDARY_FLUX_HLL, max() to fmax and added 'const' in front of constant values, as Ranocha recommended. * incooperated Ranochas comment on the preprocessor symbols and removed a compiler warning * A new testcase: A dipole which stays next to the domain and oscillations of the magentic field on the opposite domain border. * boundary conditions for MHD * proper handling of misdefined preprocessor symbols * clear distinction between a analytic soloution and the initial and boundary values, which is needed for a new example * A new testcase: A dipole which stays next to the domain and oscillations of the magentic field on the opposite domain border. * rebase on master * ideal_MHD_Dipole.m
1 parent 143eff9 commit 7d24f33

5 files changed

Lines changed: 210 additions & 17 deletions

File tree

examples/ideal_MHD_Dipole.m

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
clc
2+
clear
3+
close all
4+
5+
addpath('../matlab')
6+
7+
BalanceLaws.prepare_vars();
8+
global I_Mesh I_TI I_BalanceLaws I_Tech I_RunOps I_Results
9+
10+
N = uint32(100);
11+
I_Mesh('NODES_X') = N; I_Mesh('NODES_Y') = N; I_Mesh('NODES_Z') = N;
12+
I_Mesh('XMIN') = 0.0; I_Mesh('XMAX') = 1.0;
13+
I_Mesh('YMIN') = 0.0; I_Mesh('YMAX') = 1.0;
14+
I_Mesh('ZMIN') = 0.0; I_Mesh('ZMAX') = 1.0;
15+
16+
I_TI('final_time') = 1;
17+
I_TI('cfl') = 0.65;
18+
19+
dt = I_TI('cfl') * 1.0 / double(I_Mesh('NODES_Y'));
20+
num_steps = ceil(I_TI('final_time')/dt);
21+
dt = I_TI('final_time') / num_steps;
22+
23+
%Time integrator: SSPRK33 SSPRK104 CalvoFrancoRandez2R64
24+
%KennedyCarpenterLewis2R54C CarpenterKennedy2N54 ToulorgeDesmet2N84F
25+
I_TI('time_integrator') = 'CarpenterKennedy2N54';
26+
27+
I_TI('DT') = dt;
28+
I_TI('num_steps') = num_steps;
29+
30+
I_Tech('device') = 1;
31+
I_Tech('REAL') = 'double'; % float, double
32+
I_Tech('REAL4') = sprintf('%s4',I_Tech('REAL')); %Vector datatype
33+
I_Tech('memory_layout') = 'USE_STRUCTURE_OF_ARRAYS'; % USE_ARRAY_OF_STRUCTURES, USE_STRUCTURE_OF_ARRAYS
34+
35+
% Use as kernel defines to keep consistency with header files?
36+
I_BalanceLaws('NUM_CONSERVED_VARS') = 8;
37+
I_BalanceLaws('NUM_AUXILIARY_VARS') = 4;
38+
I_BalanceLaws('NUM_TOTAL_VARS') = I_BalanceLaws('NUM_CONSERVED_VARS') + I_BalanceLaws('NUM_AUXILIARY_VARS');
39+
40+
%Compiler based optimizations
41+
if strcmp(I_Tech('REAL'),'float')
42+
I_Tech('optimizations') = ' -cl-mad-enable -cl-no-signed-zeros -cl-finite-math-only -cl-single-precision-constant';
43+
else
44+
I_Tech('optimizations') = ' -cl-mad-enable -cl-no-signed-zeros -cl-finite-math-only';
45+
end
46+
47+
I_RunOps('periodic') = 'NONE'; % 'NONE', 'USE_PERIODIC'; must be set to 'USE_PERIODIC'
48+
% if periodic boundary conditions should be used
49+
50+
I_RunOps('order') = 4; I_RunOps('operator_form') = 'classical'; % order: 2, 4, 6; operator_form: classical, extended
51+
I_RunOps('conservation_laws') = 'ideal_MHD';
52+
I_RunOps('testcase') = 'far_dipole';
53+
I_RunOps('plot_numerical_solution') = 'z';
54+
I_RunOps('save_integrals_over_time') = false;
55+
% Choose between L2 and LInfinity norm for error calculation
56+
I_RunOps('norm') = 'LInf'; % L2, LInf
57+
%% Initialize variables
58+
[field_u1, field_u2] = BalanceLaws.initialize();
59+
60+
fprintf('Testcase: %s \nOrder: %d \nTime integrator: %s\nDT: %.16e N_STEPS: %5d FINAL_TIME: %.16e\nDX: %.16e NODES_X: %5d\nDY: %.16e NODES_Y: %5d\nDZ: %.16e NODES_Z: %5d \nREAL: %s\n\n',...
61+
I_RunOps('testcase'), I_RunOps('order'), I_TI('time_integrator'), I_TI('DT'), I_TI('num_steps'), I_TI('final_time'), I_Mesh('DX'), I_Mesh('NODES_X'), I_Mesh('DY'), I_Mesh('NODES_Y'), I_Mesh('DZ'), I_Mesh('NODES_Z'), I_Tech('REAL'));
62+
%% Compute numerical solution
63+
BalanceLaws.compute_numerical_solution(field_u1, field_u2);
64+
fprintf('Total runtime: %.3f seconds Kernel runtime: %d\n', I_Results('runtime'), I_Results('kernel_runtime'));
65+
66+
rel_err = I_Results('rel_err');
67+
for comp=0:I_BalanceLaws('NUM_CONSERVED_VARS') - 1
68+
fprintf('Relative Error of Field Component %d: %.15f %%\n', comp, 100*rel_err(comp + 1))
69+
end
70+
71+
%% Plot numerical solution
72+
num_nodes = I_Mesh('NODES_X')*I_Mesh('NODES_Y')*I_Mesh('NODES_Z');
73+
if strcmp(I_Tech('memory_layout'), 'USE_ARRAY_OF_STRUCTURES')
74+
field_u1_plot = reshape(field_u1(1:num_nodes*I_BalanceLaws('NUM_TOTAL_VARS')), [I_BalanceLaws('NUM_TOTAL_VARS'), num_nodes]);
75+
elseif strcmp(I_Tech('memory_layout'), 'USE_STRUCTURE_OF_ARRAYS')
76+
field_u1_tmp = reshape(field_u1, I_Tech('NUM_NODES_PAD'), I_BalanceLaws('NUM_TOTAL_VARS'));
77+
field_u1_plot = field_u1_tmp(1:num_nodes, :)';
78+
else
79+
error('You must USE_ARRAY_OF_STRUCTURES or USE_STRUCTURE_OF_ARRAYS.')
80+
end
81+
82+
%Optional plots
83+
if ismember(lower(char(I_RunOps('plot_numerical_solution'))),{'x','y','z','xy', 'xz', 'yz', 'xyz'})
84+
plot_2D(field_u1_plot, I_RunOps('plot_numerical_solution'),...
85+
I_Mesh('NODES_X'), I_Mesh('NODES_Y'), I_Mesh('NODES_Z'), 'Numerical Solution', 6, 8);
86+
end

include_defines/ideal_MHD_defines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,15 @@ TODO: JANHUNEN_CENTRAL, BRACKBILL_BARNES_CENTRAL, cf.
5757
*/
5858
#define USE_SOURCE_GODUNOV_CENTRAL
5959

60+
6061
// Boundary Fluxes: USE_BOUNDARY_FLUX_HLL
6162
#define USE_BOUNDARY_FLUX_HLL
6263

6364
// Speeds: USE_HLL_SPEED_KUSANO USE_HLL_SPEED_BKW
6465
#define USE_HLL_SPEED_BKW
6566

6667

68+
6769
enum Fields {
6870
// Density
6971
Field_rho,

include_physics/ideal_MHD.h

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -362,9 +362,9 @@ inline void compute_ext_num_flux_z(REAL const* uk, REAL const* um, REAL* ext_num
362362
inline void init_fields(uint ix, uint iy, uint iz, global REAL* u) {
363363

364364
REAL rho = rho_initial(ix, iy, iz, (REAL)(0));
365-
REAL p = p_initial(ix, iy, iz, (REAL)(0));
366-
REAL4 uinit = u_initial(ix, iy, iz, (REAL)(0));
367-
REAL4 binit = b_initial(ix, iy, iz, (REAL)(0));
365+
REAL p = p_initial(ix, iy, iz, (REAL)(0));
366+
REAL4 uinit = u_initial(ix, iy, iz, (REAL)(0));
367+
REAL4 binit = b_initial(ix, iy, iz, (REAL)(0));
368368

369369
REAL um[NUM_TOTAL_VARS] = {0};
370370

@@ -387,6 +387,7 @@ inline void init_fields(uint ix, uint iy, uint iz, global REAL* u) {
387387
// Surface terms
388388
//--------------------------------------------------------------------------------------------------
389389

390+
390391
#ifndef USE_PERIODIC
391392

392393
#define sq(x) ((x)*(x))
@@ -432,6 +433,7 @@ inline void calc_flux_h(const REAL *u, REAL *flux){
432433
}
433434

434435

436+
435437
#if defined USE_BOUNDARY_FLUX_HLL
436438

437439
inline void calc_num_flux(REAL al, REAL ar, REAL *ul, REAL *ur, REAL *fluxl, REAL *fluxr, REAL *num_flux){
@@ -443,7 +445,7 @@ inline void calc_num_flux(REAL al, REAL ar, REAL *ul, REAL *ur, REAL *fluxl, REA
443445
else if(0 < ar) {
444446
for (i = 0; i < NUM_CONSERVED_VARS; i++)
445447
num_flux[i] = ((ar*fluxl[i]-al*fluxr[i]) + ar*al*(ur[i]-ul[i]))/(ar-al);
446-
}
448+
}
447449
else {
448450
for (i = 0; i < NUM_CONSERVED_VARS; i++)
449451
num_flux[i] = fluxr[i];
@@ -453,7 +455,7 @@ inline void calc_num_flux(REAL al, REAL ar, REAL *ul, REAL *ur, REAL *fluxl, REA
453455

454456
inline void calc_hll_speeds(REAL* ul, REAL* ur, REAL *cl, REAL* cr, int dir) {
455457
#ifdef USE_HLL_SPEED_BKW
456-
// Speeds from
458+
// Speeds from
457459
// A multiwave approximate Riemann solver for ideal MHD based on relaxation I and II
458460
// Bouchut, Klingenberg and Waagan (2007 and 2012)
459461

@@ -498,8 +500,7 @@ inline void calc_hll_speeds(REAL* ul, REAL* ur, REAL *cl, REAL* cr, int dir) {
498500
// Default?
499501
}
500502

501-
502-
REAL dp_drho_cs_l = GAMMA*P_l/rho_l;
503+
REAL dp_drho_cs_l = GAMMA*P_l/rho_l;
503504
REAL dp_drho_cs_r = GAMMA*P_r/rho_r;
504505
REAL pi_l = P_l + 0.5 * Bsq_l - 0.5 * Bx_l * Bx_l;
505506
REAL pi_r = P_r + 0.5 * Bsq_r - 0.5 * Bx_r * Bx_r;
@@ -525,10 +526,10 @@ inline void calc_hll_speeds(REAL* ul, REAL* ur, REAL *cl, REAL* cr, int dir) {
525526
// eq. 3.13
526527
*cl = -rho_l * a_0l - alpha * rho_l * (PLUS(u_l - u_r) + PLUS(pi_r - pi_l) / (rho_l * a_ql + rho_r * a_qr));
527528
*cr = rho_r * a_0r + alpha * rho_r * (PLUS(u_l - u_r) + PLUS(pi_l - pi_r) / (rho_l * a_ql + rho_r * a_qr));
528-
return;
529+
return;
529530

530531
#elif defined USE_HLL_SPEED_KUSANO
531-
// Speeds for the HLL solver are from equation (12) of
532+
// Speeds for the HLL solver are from equation (12) of
532533
// A multi-state HLL approximate Riemann solver for ideal magnetohydrodynamics
533534
// Miyoshi and Kusano (2005)
534535

@@ -566,7 +567,7 @@ inline void calc_hll_speeds(REAL* ul, REAL* ur, REAL *cl, REAL* cr, int dir) {
566567
#endif //USE_HLL_SPEED_KUSANO
567568
}
568569

569-
570+
570571
#endif //USE_BOUNDARY_FLUX_HLL
571572
#endif //USE_PERIODIC
572573

@@ -577,7 +578,7 @@ inline void add_surface_terms(REAL time, uint ix, uint iy, uint iz, const global
577578
#ifdef USE_BOUNDARY_FLUX_HLL
578579
int i;
579580
REAL um[NUM_TOTAL_VARS] = {0.0};
580-
get_field(ix, iy, iz, 0, 0, 0, u, um);
581+
get_field(ix, iy, iz, 0, 0, 0, u, um);
581582
REAL4 b_bound = b_boundary(ix, iy, iz, time);
582583
REAL4 u_bound = u_boundary(ix, iy, iz, time);
583584
REAL rho_bound = rho_boundary(ix, iy, iz, time); //(REAL)1;
@@ -604,9 +605,9 @@ inline void add_surface_terms(REAL time, uint ix, uint iy, uint iz, const global
604605
REAL fluxb[NUM_CONSERVED_VARS] = {0.0};
605606

606607
REAL alx, arx, aly, ary, alz, arz;
607-
608+
608609
if (check_bound_xr(ix, 1)) {
609-
calc_hll_speeds(um, ub, &alx, &arx, 0);
610+
calc_hll_speeds(um, ub, &alx, &arx, 0);
610611
calc_flux_f(um, fluxm);
611612
calc_flux_f(ub, fluxb);
612613
calc_num_flux(alx, arx, um, ub, fluxm, fluxb, flux);
@@ -622,7 +623,7 @@ inline void add_surface_terms(REAL time, uint ix, uint iy, uint iz, const global
622623
du_dt[i] += (REAL)(M_INV[0] / DX) * (flux[i] - fluxm[i]);
623624
}
624625

625-
if (check_bound_yr(iy, 1)) {
626+
if (check_bound_yr(iy, 1)) {
626627
calc_hll_speeds(um, ub, &aly, &ary, 1);
627628
calc_flux_g(um, fluxm);
628629
calc_flux_g(ub, fluxb);

include_testcases/ideal_MHD_alfven_periodic.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ inline REAL rho_boundary(uint ix, uint iy, uint iz, REAL time) {
9090
}
9191

9292

93-
9493
/* initial conditions for the simulation */
9594

9695
inline REAL4 b_initial(uint ix, uint iy, uint iz, REAL time){
@@ -104,11 +103,10 @@ inline REAL4 u_initial(uint ix, uint iy, uint iz, REAL time){
104103
}
105104

106105
inline REAL p_initial(uint idx, uint iy, uint iz, REAL time){
107-
108106
return (REAL)(1);
109107
}
110108

111109
inline REAL rho_initial(uint idx, uint iy, uint iz, REAL time){
112110

113111
return (REAL)(1);
114-
}
112+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// This project is licensed under the terms of the Creative Commons CC BY-NC-ND 4.0 license.
2+
3+
//--------------------------------------------------------------------------------------------------
4+
// Functions for field initialisation
5+
//--------------------------------------------------------------------------------------------------
6+
7+
8+
// Example for inhomogeneous magnetic fields
9+
// A dipole outside of the domain
10+
// paramters
11+
REAL4 constant M = {0.0, 0.0, 1.0, 0.0};
12+
REAL4 constant X_0 = {-1.0, 0.5, 0.0, 0.0};
13+
REAL constant A0 = 0.1;
14+
REAL constant omega = 6.28 * 10;
15+
/*
16+
There is no analytical solution for this simulation
17+
*/
18+
inline REAL4 u_analytical(uint ix, uint iy, uint iz, REAL time) {
19+
20+
return (REAL4) {(REAL)(0), (REAL)(0), (REAL)(0), (REAL)(0)};
21+
}
22+
23+
inline REAL4 b_analytical(uint ix, uint iy, uint iz, REAL time) {
24+
25+
return (REAL4) {(REAL)(0), (REAL)(0), (REAL)(0), (REAL)(0)};
26+
}
27+
28+
// Magnetic Dipole definition out of
29+
// Course of Theoretical Physics: The Classical Theory of Fields
30+
// L.D. Landau and E. M. Lifschitz
31+
// (1951)
32+
33+
inline REAL4 b_dipole(REAL4 X, REAL4 M) {
34+
REAL inorm = rsqrt(X.x*X.x + X.y*X.y + X.z*X.z);
35+
REAL4 n = inorm * X;
36+
REAL4 H = (3 * n * (M * n) - M) * inorm * inorm * inorm;
37+
return H;
38+
}
39+
40+
/* initial values for p, rho, B and the velocity */
41+
42+
inline REAL p_initial(uint ix, uint iy, uint iz, REAL time){
43+
44+
return (REAL)(1.0);
45+
}
46+
47+
inline REAL rho_initial(uint ix, uint iy, uint iz, REAL time){
48+
49+
return (REAL)(1.0);
50+
}
51+
52+
53+
54+
inline REAL4 b_initial(uint ix, uint iy, uint iz, REAL time){
55+
REAL x = XMIN + ix * DX - X_0.x;
56+
REAL y = YMIN + iy * DY - X_0.y;
57+
REAL z = ZMIN + iz * DZ - X_0.z;
58+
59+
return b_dipole((REAL4){x, y, z, 0}, M);
60+
}
61+
62+
inline REAL4 u_initial(uint ix, uint iy, uint iz, REAL time){
63+
64+
return (REAL4){0, 0, 0, 0} ;
65+
}
66+
67+
68+
/*
69+
Boundary condition of the magnetic field.
70+
The absolute magnetic field of the right boundary in x-direction oscillates.
71+
We would like to see the waves which propagate to the left.
72+
*/
73+
inline REAL4 b_boundary(uint ix, uint iy, uint iz, REAL time) {
74+
REAL x = XMIN + ix * DX;
75+
REAL y = YMIN + iy * DY;
76+
REAL z = ZMIN + iz * DZ;
77+
REAL amplitude;
78+
REAL4 init_b = b_initial(ix, iy, iz, (REAL)0.0);
79+
if (x > 0.9) {
80+
amplitude = 1 + A0 * sin(omega*time) * (x - 0.9) * 10;
81+
}
82+
else {
83+
amplitude = 1;
84+
}
85+
86+
return init_b * amplitude;
87+
}
88+
89+
/*
90+
Boundary condition of the velocity field.
91+
*/
92+
inline REAL4 u_boundary(uint ix, uint iy, uint iz, REAL time) {
93+
94+
return u_initial(ix, iy, iz, time);
95+
}
96+
97+
inline REAL rho_boundary(uint ix, uint iy, uint iz, REAL time) {
98+
99+
return rho_initial(ix, iy, iz, time);
100+
}
101+
102+
inline REAL p_boundary(uint ix, uint iy, uint iz, REAL time){
103+
104+
return p_initial(ix, iy, iz, time);
105+
106+
}

0 commit comments

Comments
 (0)