|
[Sponsors] |
Improved solver data output / tracking / visualization |
|
LinkBack | Thread Tools | Search this Thread | Display Modes |
May 6, 2015, 10:01 |
Improved solver data output / tracking / visualization
|
#1 |
Senior Member
Join Date: Oct 2013
Posts: 397
Rep Power: 19 |
I have been somewhat unhappy with the way solver output works in OpenFOAM. The common approach is that the solver writes a log file which is then parsed with external tools. However, atleast when creating a solver oneself, better control over the output might be desireable. In my case, this results in writing csv files with lots of output data for analysis.
I've created a solution for this that I would like to present here. I wrote a class that can be used in the solver to store values. The class has support for structured output based on time steps and two nested loops, so the results may be viewed for each time step, each outer loop or every inner loop iteration. Separate csv files will be written for these cases so they are easier to plot. The solver only needs some tiny adjustments, namely, you need to tell the csv file when a new timestep, outer loop step or inner loop substep occurs. Apart from that, you can use the class anywhere to output any kind of data you like. For plotting I use kst plot. It's a handy tool that can be used to configure different views on the result data, so I can look at the whole data, only the last x steps, etc. For me it's much more flexible than gnuplot for data visualization. Attached you can find the files for the csv class. Below is an example use case in a solver. It's not tested or useful in any real way but serves to demonstrate the usage of this class: Code:
#include "AllKindsOfThings.H" #include "csvWriter.H" int main(int argc, char *argv[]) { #include "someStuff.H" //Create the csvWriter objects on the heap so they can be initialized later autoPtr<csvWriter> csv; autoPtr<csvWriter> residuals; Info << "Start time: " << runTime.startTime() << endl; Info << "End time: " << runTime.endTime() << endl; Info << "dt: " << runTime.deltaT() << endl; Info << "\nStarting time loop\n" << endl; while (runTime.run()) { //Start time of the current time step for profiling scalar timeStepStart = runTime.elapsedCpuTime(); runTime++; Info << "Time = " << runTime.timeName() << nl << endl; Info << "deltaT = " << runTime.deltaT().value() << endl; //Initialize the csv objects on the first step and set the current times on further steps //If you want to put the calls to increaseTime at the end of the time loop you need to initialize the csvWriter objects before the time lop with startTime + deltaT instead if(runTime.timeIndex() == runTime.startTimeIndex() + 1) { csv.set(new csvWriter("output", runTime.time().value() * 1e6, true)); residuals.set(new csvWriter("residuals", runTime.time().value() * 1e6, false)); //Stored residuals shouldn't be printed by default } else { csv->increaseTime(runTime.time().value() * 1e6); residuals->increaseTime(runTime.time().value() * 1e6); } //Main outer convergence loop while (pimple.loop()) { while(bSubStepLoop) { //Solve some equation and write the convergence results to the csv files. solverPerformance perf = solve(SomeEquation); residuals->store("SomeEquation_initial", perf.initialResidual(), "SomeEquation_final", perf.finalResidual(), "SomeEquation_iterations", perf.nIterations()); //store some field values and print them csv->store("Somefield_min", gMin(someField), "Somefield_max", gMax(someField)); //here we increase the index of the substep loop csv->increaseSubStep(); residuals->increaseSubStep(); } //Store the time of the current outer loop iteration in ms csv->store("OuterLoopTime", (runTime.elapsedCpuTime() - timeStepStart) * 1000); //Here we increase the index of the step loop csv->increaseStep(); residuals->increaseStep(); } runTime.write(); //Store the total runtime but don't print it csv->store("Runtime", runTime.elapsedCpuTime(), false); Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s" << ", ClockTime = " << runTime.elapsedClockTime() << " s" << ", Time step duration = " << runTime.elapsedClockTime() - timeStepStart << " s" << nl << endl; } runTime.writeNow(); Info << "Last write at t=" << runTime.timeName() << endl; Info<< "\nEnd\n" << endl; return 0; } Last edited by chriss85; May 13, 2015 at 08:51. |
|
May 13, 2015, 08:55 |
|
#2 |
Senior Member
Join Date: Oct 2013
Posts: 397
Rep Power: 19 |
I've added an example code for demonstration.
This method has proved to be quite useful for me in monitoring the convergence behavior of my code and optimizing the performance. Being able to quickly view all kinds of convergence and performance data in realtime makes it much easier to make the solver code work as best as possible Let me know if you feel there is anything missing in this approach! |
|
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
which solver for particle tracking through a fluid for lagrangian based method? | ranasa | OpenFOAM Running, Solving & CFD | 0 | August 9, 2014 04:09 |
solver stop problem in Lagrangian Particle Tracking | sakurabogoda | CFX | 3 | October 5, 2012 07:09 |
Quarter Burner mesh with periosic condition | SamCanuck | FLUENT | 2 | August 31, 2011 12:34 |
Working directory via command line | Luiz | CFX | 4 | March 6, 2011 21:02 |
why the solver reject it? Anyone with experience? | bearcat | CFX | 6 | April 28, 2008 15:08 |