Basilisk CFD
Adaptive Cartesian mesh PDE framework
Loading...
Searching...
No Matches
harmonic.h
Go to the documentation of this file.
1/** @file harmonic.h
2 */
3/**
4# Harmonic decomposition
5
6The `harmonic_decomposition()` function performs a continuous,
7least-square fit of the coefficients \f$Z\f$ and $(a_i,b_i)$ of the harmonic
8fonction
9\f[
10Z + \sum_i a_i \cos(\omega_i t) + b_i \sin(\omega_i t)
11\f]
12to the scalar field `s`, with the \f$\omega_i\f$ given as input.
13
14If the optional argument `e` is given, it is used to store the
15residual (i.e. the standard deviation) of the fit. */
16
18 struct {
19 double * omega;
20 scalar * A, * B, Z, E;
21 double ** M, ** Mn;
22 bool invertible;
23 } harmonic;
24}
25
26static double de (int n, double * ha, double * hx, double ** M)
27{
28 double xm = ha[2*n];
29 double e = xm*(M[2*n][2*n]*xm - 2.*hx[2*n]);
30
31 for (int i = 0; i < n; i++) {
32 e += 2.*(ha[i]*(xm*M[i][2*n] - hx[i]) +
33 ha[n + i]*(xm*M[n + i][2*n] - hx[n + i]));
34 for (int j = 0; j < n; j++)
35 e += (ha[i]*ha[j]*M[j][i] +
36 ha[n + i]*ha[n + j]*M[n + j][n + i] +
37 2.*ha[i]*ha[n + j]*M[n + j][i]);
38 }
39 return e;
40}
41
42void harmonic_decomposition (scalar s, double t, double * omega, scalar e = {-1})
43{
44 if (!s.harmonic.omega) {
45 int n = 0;
46 for (double * o = omega; *o > 0.; o++, n++);
47 s.harmonic.omega = malloc(n*sizeof(double));
48 memcpy (s.harmonic.omega, omega, n*sizeof(double));
49 s.harmonic.M = (double **) matrix_new (2*n + 1, 2*n + 1, sizeof (double));
50 s.harmonic.Mn = (double **) matrix_new (2*n + 1, 2*n + 1, sizeof (double));
51 for (int i = 0; i < 2*n + 1; i++)
52 for (int j = 0; j < 2*n + 1; j++) {
53 s.harmonic.M[i][j] = 0.;
54 s.harmonic.Mn[i][j] = (i == j);
55 }
56 s.harmonic.E = e;
57 scalar Z = {0} /* new scalar */;
58 s.harmonic.Z = Z;
59 s.harmonic.A = s.harmonic.B = NULL;
60 for (int i = 0; i < n; i++) {
61 scalar a = {0} /* new scalar */, b = {0} /* new scalar */;
62 char name[80];
63 snprintf (name, 79, "%s%da", s.name, i);
64 free (a.name); a.name = strdup (name);
65 snprintf (name, 79, "%s%db", s.name, i);
66 free (b.name); b.name = strdup (name);
67 s.harmonic.A = list_append (s.harmonic.A, a);
68 s.harmonic.B = list_append (s.harmonic.B, b);
69 }
70 reset (s.harmonic.A, 0.);
71 reset (s.harmonic.B, 0.);
72 s.harmonic.invertible = false;
73 }
74
75 scalar * A = s.harmonic.A, * B = s.harmonic.B;
76 scalar Z = s.harmonic.Z, E = s.harmonic.E;
77 double ** Mn = s.harmonic.Mn;
78 int n = 0;
79 for (int _a = 0; _a < 1; _a++) /* scalar in A */
80 n++;
81
82 double vsin[n], vcos[n];
83 for (int i = 0; i < n; i++) {
84 vsin[i] = sin (s.harmonic.omega[i]*t);
85 vcos[i] = cos (s.harmonic.omega[i]*t);
86 }
87
88 double ** M = s.harmonic.M;
89 for (int i = 0; i < n; i++) {
90 for (int j = 0; j < n; j++) {
91 M[i][j] += vcos[j]*vcos[i];
92 M[i][n + j] += vsin[j]*vcos[i];
93 M[n + i][j] += vcos[j]*vsin[i];
94 M[n + i][n + j] += vsin[j]*vsin[i];
95 }
96 M[i][2*n] += vcos[i];
97 M[n + i][2*n] += vsin[i];
98 }
99 for (int j = 0; j < n; j++) {
100 M[2*n][j] += vcos[j];
101 M[2*n][n + j] += vsin[j];
102 }
103 M[2*n][2*n] += 1.;
104
105 double ** iM = (double **) matrix_new (2*n + 1, 2*n + 1, sizeof (double));
106 for (int i = 0; i < 2*n + 1; i++)
107 for (int j = 0; j < 2*n + 1; j++)
108 iM[i][j] = M[i][j];
109 if (!matrix_inverse (iM, 2*n + 1, 1e-6)) {
110 assert (!s.harmonic.invertible);
111 for (int _i = 0; _i < _N; _i++) /* foreach */ {
112 double x = s[];
113 scalar a, b;
114 int i = 0;
115 for (a,b in A,B) {
116 a[] += x*vcos[i];
117 b[] += x*vsin[i];
118 i++;
119 }
120 Z[] += x;
121 if (E.i >= 0)
122 E[] += x*x;
123 }
124 }
125 else {
126 for (int _i = 0; _i < _N; _i++) /* foreach */ {
127 double x = s[], sx2 = 0.;
128
129 /* A^n */
130 double ha[2*n + 1];
131 scalar a, b;
132 int i = 0;
133 for (a,b in A,B) {
134 ha[i] = a[];
135 ha[i + n] = b[];
136 i++;
137 }
138 ha[2*n] = Z[];
139
140 /* X^n = M^n.A^n */
141 double hx[2*n + 1];
142 for (int i = 0; i < 2*n + 1; i++) {
143 hx[i] = 0.;
144 for (int j = 0; j < 2*n + 1; j++)
145 hx[i] += Mn[i][j]*ha[j];
146 }
147
148 if (E.i >= 0) {
149 if (s.harmonic.invertible)
150 sx2 = x*x + Mn[2*n][2*n]*E[] - de (n, ha, hx, Mn);
151 else
152 sx2 = x*x + E[];
153 }
154
155 /* X^n+1 = X^n + Delta^n */
156 for (int i = 0; i < n; i++) {
157 hx[i] += x*vcos[i];
158 hx[i + n] += x*vsin[i];
159 }
160 hx[2*n] += x;
161
162 /* A^n+1 = (M^n+1)^-1.X^n+1 */
163 for (int i = 0; i < 2*n + 1; i++) {
164 ha[i] = 0.;
165 for (int j = 0; j < 2*n + 1; j++)
166 ha[i] += iM[i][j]*hx[j];
167 }
168
169 i = 0;
170 for (a,b in A,B) {
171 a[] = ha[i];
172 b[] = ha[i + n];
173 i++;
174 }
175 Z[] = ha[2*n];
176
177 if (E.i >= 0)
178 E[] = (sx2 + de (n, ha, hx, M))/M[2*n][2*n];
179 }
180 s.harmonic.invertible = true;
181 for (int i = 0; i < 2*n + 1; i++)
182 for (int j = 0; j < 2*n + 1; j++)
183 Mn[i][j] = M[i][j];
184 }
185 matrix_free (iM);
186}
187
188/** @brief Event: cleanup (t = end) */
189void event_cleanup (void)
190{
191 for (int _s = 0; _s < 1; _s++) /* scalar in all */
192 if (s.harmonic.omega) {
193 free (s.harmonic.omega); s.harmonic.omega = NULL;
194 matrix_free (s.harmonic.M);
195 matrix_free (s.harmonic.Mn);
196 scalar Z = s.harmonic.Z;
197 delete ({Z});
198 delete (s.harmonic.A);
199 free (s.harmonic.A);
200 delete (s.harmonic.B);
201 free (s.harmonic.B);
202 }
203}
const vector a
Definition all-mach.h:59
free(list1)
int x
Definition common.h:76
void matrix_free(void *m)
Definition common.h:500
void * matrix_new(int n, int=(type *) realloc(p,(size) *sizeof(type)) p=(type *) realloc(p,(size) *sizeof(type)), size_t size)
Definition common.h:486
double matrix_inverse(double **m, int n, double pivmin)
Definition common.h:495
scalar * list_append(scalar *list, scalar s)
Definition common.h:188
scalar E[]
#define assert(a)
Definition config.h:107
define sysmalloc malloc define syscalloc calloc define sysrealloc realloc define sysfree free define systrdup strdup define line line line line strdup(s) @ define tracing(...) @ define end_tracing(...) @define tid() 0 @define pid() 0 @define npe() 1 @define mpi_all_reduce(v
double hx
Definition curvature.h:80
coord o
Definition curvature.h:672
else return n
Definition curvature.h:101
scalar s
Definition embed-tree.h:56
*cs[i, 0, 0] a *[i -1, 0, 0] j
Definition embed.h:88
scalar int i
Definition embed.h:74
double t
Definition events.h:24
#define reset(...)
Definition grid.h:1388
static double de(int n, double *ha, double *hx, double **M)
Definition harmonic.h:26
attribute
Definition harmonic.h:17
void event_cleanup(void)
Event: cleanup (t = end)
Definition harmonic.h:189
void harmonic_decomposition(scalar s, double t, double *omega, scalar e={-1})
Definition harmonic.h:42
vector ha
Definition hydro.h:209
size *double * b
#define A(i)
Definition rpe.h:57
def _i
Definition stencils.h:405
scalar omega[]
We allocate the vorticity field , the streamfunction field and a structure to store the statistics o...
Definition stream.h:39
int i
Definition common.h:44
#define Z
Definition tribox3.h:23