User Tools

Site Tools


docs:classes:flowfield

Differences

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

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
docs:classes:flowfield [2009/02/16 16:26]
wikiadmin
docs:classes:flowfield [2009/02/17 08:36]
gibson
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.+   * algebraicdifferential, 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 28: 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 35: Line 36:
    ​FlowField omega = curl(u);    ​FlowField omega = curl(u);
 </​code>​ </​code>​
- 
 ===== Algebraic and differential operators ===== ===== Algebraic and differential operators =====
  
Line 42: 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 68: 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 89: 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 144: 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.txt · Last modified: 2010/02/02 07:55 (external edit)