docs:classes:flowfield

This shows you the differences between two versions of the page.

Both sides previous revision Previous revision Next revision | Previous revision | ||

docs:classes:flowfield [2009/02/16 16:22] wikiadmin |
docs:classes:flowfield [2010/02/02 07:55] (current) |
||
---|---|---|---|

Line 15: | Line 15: | ||

are stored as variables of type FlowField. The main functionality of the FlowField class is | are stored as variables of type FlowField. The main functionality of the FlowField class is | ||

- | * algebraic and differential operations, +/-, +=, ∇, ∇<sup>2</sup>, norms, inner products, etc. | + | * algebraic, differential, and symmetry operations, +/-, +=, ∇, ∇<sup>2</sup>, norms, inner products, etc. |

* transforming back and forth between spectral coefficients <latex> \hat{u}_{k_x k_y k_z j}</latex> and gridpoint values <latex>u_j (x_{n_x}, y_{n_y}, z_{n_z})</latex> | * transforming back and forth between spectral coefficients <latex> \hat{u}_{k_x k_y k_z j}</latex> and gridpoint values <latex>u_j (x_{n_x}, y_{n_y}, z_{n_z})</latex> | ||

* serving as input to DNS algorithms, which map velocity fields forward in time: u(x,t) → u(x, t+Δt) | * serving as input to DNS algorithms, which map velocity fields forward in time: u(x,t) → u(x, t+Δt) | ||

Line 21: | Line 21: | ||

* reading and writing to disk | * reading and writing to disk | ||

+ | For a complete description of FlowField functionality, see the header file {{:librarycode:flowfield.h}}. | ||

===== Constructors / Initialization ===== | ===== Constructors / Initialization ===== | ||

Line 27: | Line 28: | ||

or assigned from computations. Examples: | or assigned from computations. Examples: | ||

- | <code c++> | + | <code c++> |

FlowField f; // null value, 0-d field on 0x0x0 grid | FlowField f; // null value, 0-d field on 0x0x0 grid | ||

+ | FlowFIeld f(g); // make a copy of g | ||

FlowField u(Nx, Ny, Nz, Nd, Lx, Lz, a, b); // Nd-dim field on Nx x Ny x Nz grid, [0,Lx]x[a,b]x[0,Lz] | FlowField u(Nx, Ny, Nz, Nd, Lx, Lz, a, b); // Nd-dim field on Nx x Ny x Nz grid, [0,Lx]x[a,b]x[0,Lz] | ||

FlowField g(Nx, Ny, Nz, Nd, 2, Lx, Lz, a, b); // Nd-dim 2-tensor | FlowField g(Nx, Ny, Nz, Nd, 2, Lx, Lz, a, b); // Nd-dim 2-tensor | ||

Line 34: | Line 36: | ||

FlowField omega = curl(u); | FlowField omega = curl(u); | ||

</code> | </code> | ||

- | |||

===== Algebraic and differential operators ===== | ===== Algebraic and differential operators ===== | ||

Line 41: | Line 42: | ||

<code> | <code> | ||

+ | f *= 2.7; // f = 2.7*f | ||

f += g; // f = f + g | f += g; // f = f + g | ||

+ | f -= g; // f = f - g | ||

+ | |||

+ | f = xdiff(g); // f_i = d g_i/dx | ||

+ | f = ydiff(g); // f_i = d g_i/dy | ||

+ | f = zdiff(g); // f_i = d g_i/dz | ||

+ | f = diff(g, j, n); // f_i = d^n g_i/dx_j | ||

+ | f = diff(g, j, n); // f_i = d^n g_i/dx_j | ||

+ | f = grad(g); // f_ij = dg_i/dx_j | ||

f = curl(g); | f = curl(g); | ||

f = lapl(g); | f = lapl(g); | ||

f = div(g); | f = div(g); | ||

- | f = diff(g, j, n); // f_i = d^n g_i /dx_j | ||

- | f = grad(g); // f_ij = dg_i / dx_j | ||

f = cross(g,h); | f = cross(g,h); | ||

- | f *= 2.7; // f = 2.7*f | ||

| | ||

- | + | xdiff(g, dgdx); // same as dgdx = xdiff(g), but often more efficient | |

+ | curl(g, curl_g); // ditto | ||

+ | lapl(g, lapl_g); // ditto | ||

+ | ... | ||

Real c = L2IP(f,g); // L2 inner product of f,g | Real c = L2IP(f,g); // L2 inner product of f,g | ||

Real n = L2Norm(u); | Real n = L2Norm(u); | ||

Line 67: | Line 78: | ||

I(u) &= \frac{1}{L_x L_z} \int_{y=a,b} \frac{\partial u}{\partial y} \, dx dz | I(u) &= \frac{1}{L_x L_z} \int_{y=a,b} \frac{\partial u}{\partial y} \, dx dz | ||

\end{align*} $ </latex> | \end{align*} $ </latex> | ||

+ | |||

+ | Note that expressions such as %%f = g + h%% or %%f = 0.5*(g + h)%% are **not allowed** | ||

+ | on FlowFields, since these would generate temporary FlowField variables %%g + h%% and | ||

+ | %%0.5*(g+h)%% during expression evaluation. Instead, use sequences such as | ||

+ | |||

+ | <code> | ||

+ | // A sequence that results in f = 0.5*(g + h); | ||

+ | f = g; | ||

+ | f += h; | ||

+ | f *= 0.5; | ||

+ | </code> | ||

+ | | ||

+ | As C++ objects, FlowFields are huge monsters. It is best to minimize the amount | ||

+ | of construction, copying, assignment of FlowFields by reusing temporaries and | ||

+ | figuring out the minimal sequence of operations to get the desired result. | ||

+ | |||

+ | ===== Symmetry operations ===== | ||

+ | |||

+ | The symmetry group of FlowFields is represented by the [[fieldsymmetry|FieldSymmetry]] | ||

+ | class. Briefly, the symmetries of 3D FlowFields can be parameterized as | ||

+ | |||

+ | <latex> $ \begin{align*} | ||

+ | \sigma &= (s_x, s_y, s_x, a_x, a_z, s)\\ | ||

+ | s_x, s_y, s_z, s &= \pm 1\\ | ||

+ | a_x, a_z &\in [-0.5, 0.5) | ||

+ | \end{align*} $ </latex> | ||

+ | |||

+ | with the action of σ on a velocity field u as | ||

+ | |||

+ | <latex> | ||

+ | \sigma [u, v, w](x,y,z) = s (s_x u, s_y v, s_z w)(s_x x + a_x L_x, s_y y, s_z z + a_z L_z) | ||

+ | </latex> | ||

+ | |||

+ | A FieldSymmetry can be constructed and applied to a FlowField as follows | ||

+ | |||

+ | <code c++> | ||

+ | FieldSymmetry sigma(sx, sy, sz, ax, az, s); // construct sigma = (sx,sy,sz,ax,az,s) | ||

+ | FlowField sigma_u = sigma(u); // apply symmetry sigma to u | ||

+ | </code> | ||

+ | |||

+ | Or, the symmetric component of a field can be obtained by | ||

+ | |||

+ | <code c++> | ||

+ | FlowField Pu = u; | ||

+ | Pu += sigma(u); // Pu now equals u + sigma u | ||

+ | Pu *= 0.5; // Pu now equals (u + sigma u)/2 | ||

+ | </code> | ||

+ | |||

+ | For more examples of FlowField and FieldSymmetry usages, see | ||

+ | [[:docs:classes:fieldsymmetry|the FieldSymmetry documentation]]. | ||

+ | |||

===== Transforms and data access ===== | ===== Transforms and data access ===== | ||

Line 88: | Line 150: | ||

Because the transforms change the meaning of the FlowField's internal data | Because the transforms change the meaning of the FlowField's internal data | ||

- | array, you make sure the FlowField is in the proper state before trying to access | + | array, ***you need to make sure the FlowField is in the proper state before |

- | either its spectral coefficients or its gridpoint values. | + | trying to access either its spectral coefficients or its gridpoint values.** |

For example, to print out the entire set of gridpoint values of a FlowField, | For example, to print out the entire set of gridpoint values of a FlowField, | ||

Line 143: | Line 205: | ||

But in general it is better to use built-in FlowField operations such as %%curl%% and %%diff%% | But in general it is better to use built-in FlowField operations such as %%curl%% and %%diff%% | ||

than to loop over the data arrays, if you can. | than to loop over the data arrays, if you can. | ||

+ | |||

+ | You can also perform the $x,z$ and the $y$ transforms independently. For example, if | ||

+ | %%u%% is representing pure gridpoint values you could do this | ||

+ | |||

+ | <code c++> | ||

+ | // get a gridpoint value | ||

+ | Real u_nxnynzi = u(nx,ny,nz,i); | ||

+ | |||

+ | u.makeSpectral_xz(); | ||

+ | |||

+ | // get kx,kz Fourier coefficient at ny-th gridpoint in y | ||

+ | Complex ukxnykzi = u.cmplx(u.mx(kx), ny, u.mz(kx), i) | ||

+ | </code> | ||

+ | |||

+ | The complete set of such transform functions is | ||

+ | |||

+ | <code c++> | ||

+ | u.makeSpectral(); // to pure spectral coeffs | ||

+ | u.makePhysical(); // to pure gridpoint values | ||

+ | u.makeSpectral_xz(); // to spectral coeffs in x,z | ||

+ | u.makeSpectral_y(); // to spectral coeffs in y | ||

+ | u.makePhysical_xz(); // to gridpoint values in x,z | ||

+ | u.makePhysical_y(); // to gridpoint values in y | ||

+ | u.makeState(Physical, Spectral); // to x,z Physical and y Spectral | ||

+ | u.makeState(..., ...); // and the other three combinations of (Physical,Spectral); | ||

+ | </code> | ||

+ | The FlowField keeps track of its spectral/physical states in | ||

+ | x,z and y performs the desired transform only if it's in the | ||

+ | opposite state. You can query the state of a FlowField like this | ||

+ | |||

+ | <code c++> | ||

+ | fieldstate xzstate = u.xzstate(); | ||

+ | if (xzstate == Physical) | ||

+ | .... | ||

+ | |||

+ | fieldstate ystate = u.ystate(); | ||

+ | if (ystate == Spectral) | ||

+ | .... | ||

+ | </code> | ||

+ | |||

+ | The FlowField class has quite a few other member functions and operators. | ||

+ | For a complete description, see the header file {{:librarycode:flowfield.h}}. |

docs/classes/flowfield.1234830157.txt.gz · Last modified: 2009/02/16 16:22 by wikiadmin