Hello,
I just got started with Palabos and with C++ in general. Prior to this, I only had experience with C, so the jump from a structured programming language to a fully object-oriented one is quite large. I believe my difficulty resides more on the side of programming than Palabos itself, but I think this community is the best place to find the answers I need.
Before I started trying to fiddle with the examples to solve some problems I want to solve, I studied the Tutorial available on the wiki. But what I want to do is not covered on any example.
I started toying with /examples/showCaes/poiseuille/poiseuille.cpp, because this will be the skeleton to the problem I want to model. The code as-is saves only images snapshots with the velocity norm, but I want to write ASCII files as well with the y coordinate of the duct on the first column and the velocity norm on the second column. By following the example useIOstream.cpp, I found that I had to create a Box2D object to extract these informations from the slice I want, so I replicated this on my code. This works, but I have two problems. I’ll first pose the problems and then detail what I tried to do:
- I want my output files to be called something like “profiles_t???.dat”, where ??? is the time step. I want these ASCII files to follow the naming convention of the .gif image files, which are named “u???.gif”;
- I’m not that familiar with C++ I/O, so how do I write the output file in the way I want? On C (pseudocode) this would be something like fprintf(output, “%f %f\n”, y, velocityNorm);
For #1, I tried many things, among them writing a string and parsing this string to the object plb_ofstream as
[code=“cpp”]
ostringstream oss;
oss << “profiles_t” << iT*parameters.getDeltaT() << “.dat”;
fileName = oss.str();
//pcout << filename << endl; Debug
plb_ofstream successiveProfiles(filename);
The commented pcout is just to check on the terminal if the string was being built on the way I wanted (it was). This method does not work, and the compiler throws a lot of errors. The second thing I tried was to parse the data directly to plb_ofstream as
[code="cpp"]
plb_ofstream(successiveProfiles("profiles_t" << iT*parameters.getDeltaT() << ".dat");
but this also does not work, and the compilation terminates with an error
poiseuille.cpp: In function ‘int main(int, char**)’:
poiseuille.cpp:264:78: error: invalid operands of types ‘const char [11]’ and ‘double’ to binary ‘operator<<’
plb_ofstream successiveProfiles("profiles_t" << iT*parameters.getDeltaT() << ".dat");
^
scons: *** [poiseuille.o] Error 1
So, how do I do this? I apologize in advance for taking your time for such basic question, and thank you in advance for your time.
##########################################################
EDIT
Well, it certainly was my lack of C++. I found a (somewhat dirty) way of doing both things I need, so even though this was a very low-level question I’ll relate my solution because other newbies like me may need this.
#1 - Saving several ASCII files
I created a stringstream and a string variables called buffer and filename, respectively. With “buffer” I build the filename I want, and then I parse this to the filename variable. Then, I use plb_ofstream to open a file whose name is stored on the “filename” variable and clear the buffer for the next time iteration:
[code=“cpp”]
stringstream buffer;
string filename;
(...)
buffer << "profiles_t";
buffer << iT*parameters.getDeltaT();
buffer << ".dat";
filename = buffer.str();
pcout << filename << endl; // Just prints the contents of filename to the terminal to check if everything's allright
plb_ofstream successiveProfiles(filename.c_str());
buffer.str("");
With this, I can write the filenames as I wanted, for example, "profiles_t0.5.dat", "profiles_t1.2.dat", etc.
#2 - Writing the ASCII files with two columns, with the y position on the first and the velocity norm on the second
This was trickier, and I'm certain there's a more elegant way to do this, but what I did works. Since this is a computationally fast problem and I'm still learning, I think it's not a big hassle. I noted that by defining a Box2D with the vertical slice of interest to extract the velocities, the code useIOstream.cpp used
[code="cpp"]
Box2D profileSection(nx/2, nx/2, 0, ny-1);
successiveProfiles
<< setprecision(4)
// (2) Convert from lattice to physical units.
<< *multiply (
parameters.getDeltaX() / parameters.getDeltaT(),
// (1) Compute velocity norm along the chosen section.
*computeVelocityNorm (lattice, profileSection) )
<< endl;
but produced the output file in a single line. This is ok for people who use Matlab or Octave, but I’m more comfortable with Gnuplot, and data files like those are a bit trickier to work with. So I defined a loop over the vertical direction, from ny = 0 to ny = the maximum ny and defined a Box2D at each ny point:
[code=“cpp”]
for(ny = 0; ny <= parameters.getNy() - 1; ny ++)
{
Box2D profileSection(nx/2, nx/2, ny, ny);
successiveProfiles << setprecision(5) << ny << " " << *multiply ( parameters.getDeltaX() / parameters.getDeltaT(), *computeVelocityNorm (lattice, profileSection) ) << endl;
}
With this, my output files look the way I wanted, and are formatted in a way that Gnuplot can handle directly.
This is, obviously, not the best solution, but if possible I would like to know what's the best, most elegant way of doing this.
Thank you for your time!