CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   Writing/output of simple data into an ASCII-File (https://www.cfd-online.com/Forums/openfoam-programming-development/95274-writing-output-simple-data-into-ascii-file.html)

matthi December 12, 2011 06:57

Writing/output of simple data into an ASCII-File
 
Dear All,

The backgrund is the coupling of an external program to OpenFoam. The coupling works with a data file which is read and written alternately from the two programs. The input from the file to OpenFoam and the calling of the external porogramm works, but not the output of data from OpenFoam.

I calculate data in a self-defined boundary condition of the solver "chtMultiRegionSimpleFoam" and want to write out this data into an ASCII-File, but it doesn`t work. I searched for a long time in the forum and in the documentation and don`t find any hint for the exact syntax.

Maybe anybody can give me an advice ?

Firstly, I define an Iodictionary:

IOdictionary OutputtoFile
(
IOobject
(
"output-file",
db().time().constant(),
db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE,
true
)
);

Normally the command OutputtoFile.write() should work, but it doesn`t.
Secondly, I found two hints, that there is a bug in Version 1.7 (which I use):
http://www.cfd-online.com/Forums/ope...herfields.html
and
http://www.openfoam.com/mantisbt/view.php?id=34

The authors, that it should work like this: "OutputtoFile.Foam::regIOobject::write()"

And really, with this command, I find a file which is named "output-file" in the directory "constant" !!! It includes the formal file header which can be found in all data files. But I am not able to get the syntax for writing out any data. I define for example a scalar field with 5 variables and calculate 5 values which I want to have in the data file:
"scalarField area(number_);", where number = 5.

Now, I want to write out the scalar field "area". I tried several syntax variants, but always there is an error during the translation. Here some trials and the errors after the arrow:

OutputtoFile.Foam::regIOobject::write(area);
è derivedFvPatchFields/detchemHeatFluxTemperature/detchemHeatFluxTemperatureFvPatchScalarField.C:332 :61: error: no matching function for call to âFoam::IOdictionary::write(Foam::scalarField&)â
/home/mahe/OpenFOAM/OpenFOAM-1.7.1/src/OpenFOAM/lnInclude/regIOobject.H:216:26: note: candidate is: virtual bool Foam::regIOobject::write() const


OutputtoFile.Foam::regIOobject::write("area");
è derivedFvPatchFields/detchemHeatFluxTemperature/detchemHeatFluxTemperatureFvPatchScalarField.C:332 :63: error: no matching function for call to âFoam::IOdictionary::write(const char [22])â
/home/mahe/OpenFOAM/OpenFOAM-1.7.1/src/OpenFOAM/lnInclude/regIOobject.H:216:26: note: candidate is: virtual bool Foam::regIOobject::write() const

OutputtoFile.Foam::regIOobject::write(area&);

è
derivedFvPatchFields/detchemHeatFluxTemperature/detchemHeatFluxTemperatureFvPatchScalarField.C:332 :62: error: expected primary-expression before â)â token

It seems also not possible to write out one single number or constant ...

I don`t believe that it is so complicated in OpenFoam to write out some simple numbers to somewhere ???
I hope, there are other users concerned, who solved the problem meanwhile or look for a discussion. I would be very grateful for every helpful advice.

Greetings Matthi


adhiraj December 12, 2011 09:09

Quote:

Firstly, I define an Iodictionary:

IOdictionary OutputtoFile
(
IOobject
(
"output-file",
db().time().constant(),
db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE,
true
)
);
That would explain why you have the output file in the constant directory.
I believe that using the IOdictionary to write the solution like you have works for OpenFOAM's data structures like 'volumeScalarField's or 'surfaceScalarField' s. I have not tried it for 'scalarField's though.

If the data you want is not a standard OpenFOAM data structure I would just go with a standard C++ file write.

marupio December 12, 2011 09:34

The object registry has its own built-in format for writing every object. If you want to take control of the output, don't use an IOdictionary. Use an OFstream.

Code:

fileName outputFile(runTime.path()/runTime.timeName());
OFstream os(outputFile);

os << "This is the first line in the file.\n"
os << "scalarField area (" << areaField.size() << ";)" << endl;

And so on.

matthi December 12, 2011 09:49

Dear Adhiraj

Thanks for you fast reply.

If I want to have the file in the "constant" or the "system"-directory is not the point. Meanwhile I tried several approaches and found a small hint concerning the command ".set".

=========================
The actual status is the following:
=========================

DEFINITION OF SCALAR FIELD
----------------------------
"scalarField T_mean(number_);", where number = 5.

DEFINITION OF IODICTIONARY
----------------------------

IOdictionary OutputtoFile
(
IOobject
(
"output-file",
db().time().constant(),
db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE,
true
)
);

Then I calculate the 5 values of the scalar "T_mean".

SET AND OUTPUT
-----------------
OutputtoFile.set("T_mean",T_mean);
OutputtoFile.Foam::regIOobject::write();

Great! The output in the File "output-file" looks like:

T_mean 5 ( 300.01791 300.03583 300.05374 300.07166 300.0895 );

The values are mean temperatures of defined grid regions of a single boundary.

This is one big step further !!!

The format is not very suitable to read it in with fortran (with another code), because the number of values is variable. But I will search for a solution where alle values are in one column.

The code lines above are now positioned in the routine where the boundary conditions are defined. This is BEFORE the time step. Better would be to calculate the mean Temperatures I want to have AFTER the time step. But I don`t know how to get access to the boundary somewhere at the end of the solver to handle the output of the values AFTER the solving.

Thanks and Greetings

Matthi

matthi December 12, 2011 09:54

Hello David,

thanks for the advice. I will try this approach and see If I understand the syntax ...

Also Thanks and Greetings for you

Matthi

matthi December 12, 2011 10:22

Quote:

Originally Posted by marupio (Post 335546)
The object registry has its own built-in format for writing every object. If you want to take control of the output, don't use an IOdictionary. Use an OFstream.

Code:

fileName outputFile(runTime.path()/runTime.timeName());
OFstream os(outputFile);
 
os << "This is the first line in the file.\n"
os << "scalarField area (" << areaField.size() << ";)" << endl;

And so on.

Hello David,

thanks for the advice. I will try this approach and see If I understand the syntax ...

Also Thanks and Greetings for you

Matthi

matthi December 13, 2011 06:10

Dear Adhiraj, Dear Marupio,

thanks for your help. It works now. I used the approach of marupio. First the translation failed. The solution was to include additionally the line (#include "OFstream.H") in the routine.

Now the test code is:

DEFINITION OF SCALAR FIELD
----------------------------
scalarField T_mean(5);

Then, calculation of the 5 values of the scalar "T_mean".

OUTPUT OF SCALAR DATA
--------------------------
fileName outputFile("TEST.txt");
OFstream os(db().time().system()/outputFile);
os << "This is the first line in the file.\n";
os << T_mean.size();
os << endl;
forAll(T_mean, i)
{
os << T_mean[i];
os << endl;
}

THE DATA IN THE FILE "TEST.txt" IN THE FOLDER "system" IS
-----------------------------------------------------------
This is the first line in the file.
5
300.01791
300.03583
300.05374
300.07166
300.0895

This is a great basis for my further development.

Again Thanks a lot and many greetings

Matthi

HakikiCanakkaleli July 12, 2013 05:04

Hi

I would like to output a simple array data from a .H file to a text file. And also, I would like to read this data set from another .H file. However, I couldn't do it.

=== 1 ===

It is the array:
Code:

label array[100];
=== 2 ===

The array is filled with a group of arbitrary values.

=== 3 ===

I had tried this.

Code:

std::ofstream output;
    output.open("output.txt");
    for (label j=0; j < 100; j++) {
    output << array[j];
    output << "\n";
    }
    output.close();

=== 4 ===
When I compiled it with wmake, the following error popped up:

Code:

error: aggregate ‘std::ofstream output’ has incomplete type and cannot be defined.
=== 5 ===

I have found some other forum pages/web-stes which consider similar issues in a slightly different context. Therefore, I somehow couldn't adapt the given answers to my case.

I appreciate any help.

Many thanks in advance.

HakikiCanakkaleli July 12, 2013 11:33

The solution to my case is to change the location of output code from .H file to .C file.

Code:

#include "IFstream.H"
#include "OFstream.H"
...
    ofstream output;
    output.open("output.txt");
    for (label j=0; j < arraySize; j++) {
    output << array[j];
    output << "\n";
    }
    output.close();
...


kiddmax October 10, 2013 04:54

Hi HakikiCanakkaleli,

Maybe it is not suitable to post here, but I think you can help me, since the topic is quite similar...

My problem is like this:
I want to use sampleDict to get the velocity on a line. Since there are too many lines I need to plot, therefore it is challenging to input the start point and end point by hands. I got the coordinates of all the points in .txt file (x,y,z). Do you know how to read these data in sampleDict? I think we need a loop to use all these points, right? I really appreciate you can give some hints!

Thank you!
Best regards,
Ye

gschaider October 10, 2013 20:51

Quote:

Originally Posted by kiddmax (Post 456091)
Hi HakikiCanakkaleli,

Maybe it is not suitable to post here, but I think you can help me, since the topic is quite similar...

My problem is like this:
I want to use sampleDict to get the velocity on a line. Since there are too many lines I need to plot, therefore it is challenging to input the start point and end point by hands. I got the coordinates of all the points in .txt file (x,y,z). Do you know how to read these data in sampleDict? I think we need a loop to use all these points, right? I really appreciate you can give some hints!

Thank you!
Best regards,
Ye

If the number of sample lines is too much to enter them then postprocessing them will be even more fun. Seriously: in that case the best way is to write a script (in the scripting language of your choice) to generate a sampleDict from that file

alexlupo November 26, 2013 13:04

Hi there,
I wrote and compiled the following but it is not writing any file:

Code:

const fvMesh& mesh = this->owner().mesh();
const fileName& fName(mesh.time().timeName()/"positionsFile.xyz");
    OFstream os(fName);
    os << magU;
    os << alpha;
    os << p.position() << endl;

The thing is that I would like to output those three values every time a patch is hit by a particle.
I am anyway not sure about the path I should specify given that this variables should be printed continuously, as there will be particles hitting patches all the time.
Any suggestions would be very much appreciated!
Thanks a lot

Quote:

Originally Posted by marupio (Post 335546)
The object registry has its own built-in format for writing every object. If you want to take control of the output, don't use an IOdictionary. Use an OFstream.

Code:

fileName outputFile(runTime.path()/runTime.timeName());
OFstream os(outputFile);

os << "This is the first line in the file.\n"
os << "scalarField area (" << areaField.size() << ";)" << endl;

And so on.


alexlupo January 22, 2014 06:18

Nevermind... I solved my own problem once again...

vitors January 30, 2014 11:01

Quote:

Originally Posted by alexlupo (Post 471213)
Nevermind... I solved my own problem once again...

How did you?

alexlupo February 5, 2014 11:10

Quote:

Originally Posted by vitors (Post 472588)
How did you?

Hi vitors,
Well, there is a nice cloudFunctionObject that allows you to do that:
patchPostProcessing.
The set up of this function should be inside the cloudFunctions section in the reacting/kinematic/colliding/CloudProperties dictionary and it is similar to this one:

Code:

patchPostProcessing
    {
        maxStoredParcels 10000;
        patches
      (
        whatever_the_name_of_your_patch
        or_patches
      );
    }

Hope this helps,

Regards

vitors February 5, 2014 11:53

Thanks Alex.

Actually, this has nothing to do with the simulations I'm running now. But I was curious to know the solution. ;-)

vigneshTG November 6, 2014 10:57

Dear Foamers,

Greetings !!

Using the information in this thread, i was able to write a file containing a variable of type labelListList successfully. Thanks for sharing your knowledge. Now I would like to read this file and store it in a variable of same type (labelListList).

Can someone suggest me a way to do this ??

Asghari_M July 8, 2015 16:08

Reading/writing OpenFoam data within a loop structure
 
Hello All,
I need to modify the value of a vector used into the some files (dictionaries/fvOptions) at Openfoam into a loop striucture, too. An algorithm with loop structure can be suggested for this purpose such as follows:
1- Initialize Vector V
2- Into the loop structure:
i) Modifying some files/dictionaries based on Vector (V) by reading vector V.
ii) Running/Executing OpenFoam application with new modified files/dictionaries within OF
iii) Writing/modifying some output parameters (for example by probe) and saving them at another accessory ASCII file/program
iv) Writing/modifying V vector based on accessory ASCII file/Program gained at previous section
3- Out-processing
As you consider, vector V transfers between accessory ASCII file and main OpenFoam2.3.1 program.
Does anyone know how to do this operation by cplusplus in Ubuntu/Linux?
Thanks a lot for any advise.
M.Asghari

harsha_kulkarni April 28, 2016 04:14

Quote:

Originally Posted by matthi (Post 335549)
Dear Adhiraj

Thanks for you fast reply.

If I want to have the file in the "constant" or the "system"-directory is not the point. Meanwhile I tried several approaches and found a small hint concerning the command ".set".

=========================
The actual status is the following:
=========================

DEFINITION OF SCALAR FIELD
----------------------------
"scalarField T_mean(number_);", where number = 5.

DEFINITION OF IODICTIONARY
----------------------------

IOdictionary OutputtoFile
(
IOobject
(
"output-file",
db().time().constant(),
db(),
IOobject::NO_READ,
IOobject::AUTO_WRITE,
true
)
);

Then I calculate the 5 values of the scalar "T_mean".

SET AND OUTPUT
-----------------
OutputtoFile.set("T_mean",T_mean);
OutputtoFile.Foam::regIOobject::write();

Great! The output in the File "output-file" looks like:

T_mean 5 ( 300.01791 300.03583 300.05374 300.07166 300.0895 );

The values are mean temperatures of defined grid regions of a single boundary.

This is one big step further !!!

The format is not very suitable to read it in with fortran (with another code), because the number of values is variable. But I will search for a solution where alle values are in one column.

The code lines above are now positioned in the routine where the boundary conditions are defined. This is BEFORE the time step. Better would be to calculate the mean Temperatures I want to have AFTER the time step. But I don`t know how to get access to the boundary somewhere at the end of the solver to handle the output of the values AFTER the solving.

Thanks and Greetings

Matthi

I have wrote down for same piece of code for flux calculation

filename outputfile("OutputtoFile.txt")
.
.
.
.
.
.

scalarField fluxOut(2)
OFstream os(db().time().system()/outputFile);
os<<fluxOut.size();
os<<endl;
forAll(fluxOut,i)
{
os<<fluxOut[i];
os<<endl;
}
OutputtoFile.txt.set(fluxOut);
OutputtoFile.txt.Foam::regIOobject::write();

and got the following error
calcMassFlow.C:214:5: note: in expansion of macro ‘forAll’
forAll(fluxOut,i)
^
In file included from rhoCentralFoam.C:267:0:
calcMassFlow.C:216:20: error: invalid types ‘Foam::scalar {aka double}[Foam::label {aka int}]’ for array subscript
os<<fluxOut[i];
^
calcMassFlow.C:219:5: error: ‘OutputtoFile’ was not declared in this scope
OutputtoFile.txt.set(fluxOut);

harsha_kulkarni April 28, 2016 04:16

Quote:

Originally Posted by matthi (Post 335660)
Dear Adhiraj, Dear Marupio,

thanks for your help. It works now. I used the approach of marupio. First the translation failed. The solution was to include additionally the line (#include "OFstream.H") in the routine.

Now the test code is:

DEFINITION OF SCALAR FIELD
----------------------------
scalarField T_mean(5);

Then, calculation of the 5 values of the scalar "T_mean".

OUTPUT OF SCALAR DATA
--------------------------
fileName outputFile("TEST.txt");
OFstream os(db().time().system()/outputFile);
os << "This is the first line in the file.\n";
os << T_mean.size();
os << endl;
forAll(T_mean, i)
{
os << T_mean[i];
os << endl;
}

THE DATA IN THE FILE "TEST.txt" IN THE FOLDER "system" IS
-----------------------------------------------------------
This is the first line in the file.
5
300.01791
300.03583
300.05374
300.07166
300.0895

This is a great basis for my further development.

Again Thanks a lot and many greetings

Matthi

---------------------------------------------------------------------------------------------------

I have wrote down for same piece of code for flux calculation

filename outputfile("OutputtoFile.txt")
.
.
.
.
.
.

scalarField fluxOut(2)
OFstream os(db().time().system()/outputFile);
os<<fluxOut.size();
os<<endl;
forAll(fluxOut,i)
{
os<<fluxOut[i];
os<<endl;
}
OutputtoFile.txt.set(fluxOut);
OutputtoFile.txt.Foam::regIOobject::write();

and got the following error
calcMassFlow.C:214:5: note: in expansion of macro ‘forAll’
forAll(fluxOut,i)
^
In file included from rhoCentralFoam.C:267:0:
calcMassFlow.C:216:20: error: invalid types ‘Foam::scalar {aka double}[Foam::label {aka int}]’ for array subscript
os<<fluxOut[i];
^
calcMassFlow.C:219:5: error: ‘OutputtoFile’ was not declared in this scope
OutputtoFile.txt.set(fluxOut);


All times are GMT -4. The time now is 18:43.