Palabos user manual translation and learning (b) run the simulation and data evaluation

Run Simulation and Evaluation Data

Palabos user documentation tenth chapter and in Chapter 12

(一)Running A Simulation

The original document

Time cycles of a Palabos program

The lattice Boltzmann method (or at least, the “classical” lattice Boltzmann method as it is implemented in Palabos) consists of an explicit solver. With a single iteration step, the state of the fluid evolves from a time t to the next time t+dt. The following discussion is led in the units of the lattice, with dt=1. One time iteration of this kind takes the following form in Palabos:

  1. To start with, all fluid variables are defined at time t. The particle populations are in pre-collision state (also called “incoming populations”).
  2. The collision operator is applied to all cells. They are now in post-collision state (also called “outgoing variables”).
  3. The streaming operator is applied to the lattice.
  4. All data processors are executed, to perform non-local operations or couplings between lattices.
  5. The populations are now again in pre-collision state, but at time t+1.



The collision step (Step 2) is executed by invoking the method lattice.collide(), and the streaming step (Step 3) is called with the method lattice.stream(). These two methods can also be combined into a single call to lattice.collideAndStream(). On most hardware platforms, the collideAndStream() version is computationally more efficient, because it is executed by traveling through the memory of the lattice only once.
The data processors can be executed manually by calling the method lattice. executeInternalProcessors(), as explained in Section Executing, integrating, and wrapping up dataprocessing functionals. This is however rarely done, because the data processors are also executed automatically at the end of the function stream() and the function collideAndStream(). If you’d like to call stream() or collideAndStream without having the data processors executed, for example for debugging a program, you can use the domain-version of these functions, for example lattice.collideAndStream(lattice.getBoundingBox()).
In Palabos, data processors are always executed after the collision-streaming cycle. Consequently, non-local operations are always executed after the collision-streaming cycle, at a moment where the populations are in a pre-collision state (incoming populations). This bears no loss of generality, though, because executing an operation before the collision of time t is equivalent to executing it after the streaming of time t-1, right? The only problem arises with the initial condition, as it is most often desired to have the data processors executed exactly once at the very beginning, right after setting up the initial condition. This is achieved by calling the method lattice.initialize() right before starting the first iteration step. This method executes the data processors once, and performs an internal communication step inside the block to guarantee that its internal state is consistent.

At which point do you evaluate data?

To monitor the evolution of a program, it is useful evaluate some hydrodynamic quantities from time to time, such as the average energy:

pcout << computeAverageEnergy(lattice) << endl;

It is recommended to compute hydrodynamic variables always only when the system is in pre-collision state (incoming populations). While this distinction not really matters for the conserved variables density and velocity (they are equal in the pre- and post-collision state), it is important for the non-conserved variables such as the stress tensor. Non-conserved velocity moments can be related to hydrodynamic variables only when they are computed in the precollision state. Note that if you use the method collideAndStream(), there is no risk for doing things wrong, because you have no access to post-collision variables anyway.
Normally, the computation of hydrodynamic variables like the average energy in the example above is performed right after the call to the method collideAndStream(), because at this point all hydrodynamic variables are well defined, and correspond to the same moment in time (between collision and streaming the velocity is well defined, but the strain-rate is not). An exception is made for the internal statistics of lattice. Internal statistics are automatically computed without any impact on performance (at least not in serial program; for the parallel case, see the discussion in Section Controlling the efficiency), as a side-effect of executing the collision step. They are however evaluated for the fluid variables at time t, during the collision-streaming cycle which carries the system from time t to time t+1. It is therefore usual to access the internal statistics after the call to the method collideAndStream(). Computing the average energy as in the example above before collision-and-streaming produces the same result as accessing the average energy from internal statistics, as in the example below, after collision-and-streaming:

pcout << getStoredAverageEnergy(lattice) << endl;
Other important things to do

Numbers are often difficult to interpret. It is therefore useful to regularly produce images in your program, so that you can monitor the state of simulation, identify problems as soon as possible, and re-run the program when needed. Section Producing images in 2D and 3D simulations explains how to do this.
Finally, it is always good to save the state of a simulation from time to time, in order not to loose everything when the computer crashes, and in order to be able to recover the data if you forgot to produce a crucial output file for post-processing. This is explained in Section Checkpointing: saving and loading the state of a simulation.

Document Translation

Time period Palabos program

Siegel Boltzmann Method (or at least Palabos implemented in "classic" Siegel Boltzmann Method) contain an explicit solver. Through an iterative step, the evolution of the state of the fluid from the next time t to time t + dt. Lattice units in accordance with the following discussion dt = 1. This iterative time in Palabos takes the form of:

  1. First, all of the fluid variables are defined at time t, the particle group in the pre-collision state (also referred to as an incident particle group).
  2. Collision operation is applied to all cells. They are now in a state of collision (also referred to as "output variables").
  3. Stream operations applied to the lattice.
  4. All data processors are executed to perform the coupling operation between the non-local or grid.
  5. Now the population has returned to the state before the collision, but the time is t + 1.

Collision is performed (step 2) by calling the method lattice.collision (), then use lattice.stream () call flows to step (Step 3). These two methods may also be combined in pairs lattice.collideandstream () a single call. On most hardware platforms, greater computational efficiency collideAndStream () version, because it only runs once in memory lattice layer.
The calling may be by a method lattice.executeInternalProcessors () manually perform a data processor, such as the implementation, integration and packaging data processing functions (Executing, integrating, and wrapping up data processing functionals, document Section 16.3.4). However, this rarely happens, as a function of the data processor is the end of the stream () function and collideAndStream () is automatically performed. If you want to call stream without performing a data processor () or collideAndStream (), for example, in order to debug a program, you can use a domain versions of these functions, such as lattice.collideAndStream (lattice.getboundingbox ()).
In Palabos, the data processor is always executed after the collision flow evolution cycle. Thus, non-local operation is always executed after the collision flow cycle, this time in the pre-collision state population (incident particle group). However, this does not loss of generality, since before the time t crash perform operations equivalent to execute it after a time t-1 stream, right? The only problem on the initial conditions, because the most common situation is that the data processor is just executed once after the initial condition is set. This is accomplished by calling the method initialize () before the start of the first iteration step. This method performs only one data processor, performs internal communication and step inside its internal state to ensure that the block is the same.

Assess data at what time?

In order to develop monitoring procedures from time to time to assess some of the hydrodynamic volume it is useful, for example, the average energy:

pcout << computeAverageEnergy(lattice) << endl;

Is recommended only in the pre-collision state when the computational fluid dynamics variable (incident particle group) in the system. While this distinction is not important for the conservation of variable density and velocity (the state thereof before the collision and after the collision are equal), but non-conserved variable, such as stress tensor, it is important for the. Non-conservative velocity moment can only be associated with the hydrodynamic variables calculated in the state before the collision. Note that if you use risk collideAndStream () method, there would be an error, because the tag after the collision in any case can not be accessed.
Typically, the calling method collideAndStream calculating hydrodynamic variables (e.g., the average energy in the example above) (after), corresponding to the same time because the hydrodynamic all variables are well-defined (and flow velocity between the collision is well-defined, but not the strain rate). Statistical inner lattice points is an exception, internal statistics is no effect on the performance of the automatic calculation (at least not in the sequential program; for the parallel case, see the discussion description 15.2Controlling the efficiency subsection), this is a step of performing collision side effects. However, (from time t to time t + 1), the variables are evaluated at time t the fluid flow in a collision cycles. Thus, in general access to internal statistics after the call collideAndStream () method. In the example above, calculation before the collision with the flow of the average energy, obtaining an average statistical value of the internal energy of the flow after the collision with the following examples, the same results:

pcout << getStoredAverageEnergy(lattice) << endl;
Other important things

Numbers are often difficult to interpret. Therefore, in the program on a regular basis to generate an image it is useful so that you can monitor the status of the simulation, identify the problem as soon as possible, and rerun the program if necessary. Generate images in 2D and 3D simulation (the original section 11.5 Producing images in 2D and 3D simulations ) of section explains how to do this.
Finally, always save the simulation state is always good, so when the computer crashes will not lose everything, but if you forget to generate the output file for the key post-processing, data can be restored. This will be checked: saving and loading state analog (original Section 11.7 Checkpointing: saving and loading the state of a simulation) interpretation.

explain

This part of the program is to introduce the collision flow cycle, written in very clear, collideAndStream () method integrates data processor calculates statistical procedures can be called directly without fear of error, the data processor computing step is to act on collision and flow then, after the fact, but after a good variety of internal and boundary conditions you for your analog set, its internal PSO has not been set, or the original state, only been called initialize (), a one-time call again data processing step, PSO was formally initialized.
I sometimes use that version does not contain the original text said data processing steps, middle write the correct operation of the code which is not necessarily the correct operation of the simulation among, and finally implemented by the corresponding function call data processing steps operation, Sao operation, the resulting data looks good, but not necessarily right, hee hee hee.

(二)Data Evaluation

The original document

Overview

The variables simulated in a lattice Boltzmann program, the particle populations, contrast with the quantities a typical fluid engineer is interested in, the macroscopic variables pressure, velocity, and others. Obviously, one needs to somehow convert the data before providing it to a standard post-processing tool. Many functions for conversion, evaluation, or transformation of data are provided in Palabos, as listed in Appendix Non-mutable operations for data analysis and other purposes. In the present section, the function computeVelocity is discussed as an example, as the other functions work in a very similar way. These functions are defined for the 2D and the 3D case, and they work with atomic-blocks and multi-blocks. For the sake of illustration, the following codes refer to the 3D multi-block case.
The function computeVelocity is provided in three versions:

// Version 1
void computeVelocity(MultiBlockLattice3D<T,Descriptor>& lattice,
MultiTensorField3D<T,Descriptor<T>::d>& velocity, Box3D domain);
// Version 2
std::unique_ptr<MultiTensorField3D<T,3> >
computeVelocity(MultiBlockLattice3D<T,Descriptor>& lattice, Box3D domain);
// Version 3
std::unique_ptr<MultiTensorField3D<T,3> >
computeVelocity(MultiBlockLattice3D<T,Descriptor>& lattice);

In the first version, the velocity is computed on a sub-domain of a block-lattice, and the result is written to a corresponding sub-domain of a three-component tensor-field. The block-lattice and the tensor-field don’t need to have the same size, nor do they need to have the same internal block arrangement. If the domain exceeds the dimensions of either the block-lattice or the tensor-field, the domain is trimmed correspondingly.
In the second version, which is much more often used in practice, a tensor-field with the size of domain is automatically created and returned from the function. The auto-pointer keyword used in the return value of the function refers to a class of smart-pointers offered by the C++ standard library. From the user’s point of view, it is practically the same as a pointer. This means that you treat an object of type std::unique_ptr<MultiTensorField3D<T,3> > in the same way as you would treat an object of type MultiTensorField3D<T,3>*. The big difference between the two is that the auto-pointer has an automatic memory management mechanism, and that you never need to call the operator delete on this type of pointers. If the return value of the function were a raw pointer, you wouldn’t be able to pipeline different operators, as shown in the next section, because you’d never get an explicit pointer to them and therefore couldn’t delete them.
The following code shows a typical use case of the function computeVelocity:

pcout << *computeVelocity(lattice, domain) << endl;

Here, the computed velocity values are immediately redirected to the terminal. The star in front of the function call is used to dereference the pointer to the velocity field. At the end of this program line, the memory for the velocity field is automatically deallocated, and does not need to be disposed of explicitly.
The third version is a pure convenience function in which the argument domain is replaced by the full domain of the lattice, lattice.getBoundingBox().

Pipelining data evaluation operators

The return value of a function like computeVelocity can directly be reused as the argument of other data evaluation operators. In this way, it is possible to construct complex expressions. For example, the function computeAverage in the previous section could be replaced by a computation of the velocity field, followed by the computation of the norm-square of each element, a division by two, and finally a computation of the average value:

pcout << "The value "
      << *computeAverageEnergy(lattice) << " is the same as "
      << computeAverage(*multiply(0.5,*computeNormSqr(*computeVelocity(lattice))))
      << endl;

All the functions used in this example are listed in the Appendix Appendix: partial function/class reference. More examples of the evaluation of data, constructions of scalar fields, and combination of data evaluation operators are provided in the directory examples/codesByTopic/scalarField.

Document Translation

Overview

Variable amounts in the lattice Boltzmann simulation program, the number of particles, in contrast to the typical fluid engineer interest such as pressure, velocity, and other macro variables. Obviously, before the data is provided to the standard post-processing tools, the need to convert data in some way. Palabos provides for a number of data conversion, or conversion of the evaluation function, and for other purposes such as data analysis are listed in Appendix immutable operation (Appendix: Non-mutable operations for data analysis and other purposes). In this section, will computeVelocity function as an example for discussion, because it is very similar to the work of other functions. These functions are defined for 2D and 3D cases, they use blocks and atomic blocks. For convenience of explanation, the following code where a plurality of reference 3D.
computeVelocity function has three versions:

// Version 1
void computeVelocity(MultiBlockLattice3D<T,Descriptor>& lattice,
MultiTensorField3D<T,Descriptor<T>::d>& velocity, Box3D domain);
// Version 2
std::unique_ptr<MultiTensorField3D<T,3> >
computeVelocity(MultiBlockLattice3D<T,Descriptor>& lattice, Box3D domain);
// Version 3
std::unique_ptr<MultiTensorField3D<T,3> >
computeVelocity(MultiBlockLattice3D<T,Descriptor>& lattice);

In the first version, the speed is calculated on a sub-lattice of the domain blocks, and writes the results to the respective subdomain tensor field has three components. And tensor fields lattice block need not have the same size, do not need to have the same internal block arrangement. If the calculated field exceeds the block size or the lattice tensor field, the computational domain will be trimmed accordingly.
In the second version (more common in practice), tensor field has a domain size and return from the function automatically created. Function return values of auto-pointer key refers to a class of smart pointers c ++ standard library. From the user's point of view, it is actually the same, and pointers. This means that the processing std :: unique_ptr <MultiTensorField3D <T, 3>> type of object handling methods and MultiTensorField3D <T, 3> * the same type of object. The main difference between the two is that there is a pointer automatic automatic memory management, and you never need to call operator delete on this type of pointer. If the return value of the function is a pointer to the original, then you can not make different pipeline operations (as shown in the next section), because you never get explicit pointer pointing to them, so they can not be deleted.
The following code shows a typical function used computeVelocity Example:

pcout << *computeVelocity(lattice, domain) << endl;

Here, the calculated velocity value is immediately redirected to the terminal. Function call in front of the asterisk is used to cancel a pointer pointing velocity field of reference. At the end of this line of the program, the memory is automatically released velocity field, need not be explicitly released.
The third version is a convenient purely function, wherein the parameter field is replaced by a full field grid, i.e. lattice.getboundingbox ().

Pipeline operators Evaluation

As the return value of such a function can be directly reused as a parameter computeVelocity other data evaluation operator. In this way, we can construct complex expressions. For example, in the previous chapter computeAverage function can be used instead of the velocity field is calculated, and then the calculation method of each element squared, divided by 2, and finally calculate the average of:

pcout << "The value "
      << *computeAverageEnergy(lattice) << " is the same as "
      << computeAverage(*multiply(0.5,*computeNormSqr(*computeVelocity(lattice))))
      << endl;

All functions used in this example are in Appendix Appendix: List partial function / class reference in. Providing data on evaluation, more scalar field exemplary data structure and evaluate the operator in the composition examples / codesByTopic / scalarField directory.

explain

All data evaluation operations, format and reviewed in three ways given the same, it is recommended to use the second, you can calculate your own domain specified range.
Data evaluation operation, a lot of Appendix Appendix: Operating partial function / class reference of all functions in accordance with Appendix inside wording can be written in complex pipelined data manipulation code can not go wrong, but please be careful not to do the Appendix other complex operations than, I tried, not very controllable.
Problem solved before giving the corresponding data output, please note that the data is output to the accuracy problems when the file you need, if too little data changes, you may be when the output, the result is essentially the same, that code is written wrong, in fact, the actual situation is the result of your variable values gap is too small, post-processing is virtually absent, please pay attention to this point.

Finish

Published 15 original articles · won praise 5 · Views 3677

Guess you like

Origin blog.csdn.net/qq_28632981/article/details/104119935