CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   Fluent UDF and Scheme Programming (https://www.cfd-online.com/Forums/fluent-udf/)
-   -   How to Read a "Profile" format file in UDF? (https://www.cfd-online.com/Forums/fluent-udf/77606-how-read-profile-format-file-udf.html)

gary7 June 28, 2010 18:27

How to Read a "Profile" format file in UDF?
 
Hi buddies,

does anybody know how can I read the boundary data which is in profile file format into the intended boundary points by using UDF coding?
I know about reading a profile from Define->Profiles... menu on the boundaries but I want to know how to do that by UDF, scheme, ... coding...any idea?

I'd really appreciate your help.

dmoroian June 29, 2010 12:06

As far as I remember, the profile file format consist in a list of scheme objects, and is in ascii format. Each object is ordered the same way as the face list in the boundary from wich the profile was saved.
In other words, if you loop in a udf over the faces of the boundary and read line by line the parameter from the profile file, they are in the same order.
Using scheme is even simpler: read the entire file in one go and put it into a variable. This variable will be a list of all objects saved inside the profile (coordinates and parameters), which you can refere sequentially.

gary7 June 29, 2010 15:03

Thank you dmoroian; yes profile file format is a list of scheme objects and it is in ASCII. The problem is that how can I read in that profile file and just take out the required info (values) from it by reading a file?
Would you please give an example of the procedure you mentioned about reading the file and storing it in variable and referring sequentially in a scheme language because I'm a newbie in scheme and couldn't find much info on it.

I appreciate your help...

dmoroian June 30, 2010 04:17

Code snippet
 
Hello Gary,
I don't know how are you going to use the scheme script, but here it comes a snippet:

Code:

(define bubu (open-input-file "interestingProfile.prof"))
(define cucu (read bubu))
(close-input-port bubu)
(format #t "there are ~a objects inside the file ~%" (length cucu))
(format #t "header info: ~a~%" (list-ref cucu 0))
(format #t "name of the first object: ~a~%" (list-ref (list-ref cucu 1) 0)

Have a look at any book about scheme language (e.g. http://www.scheme.com/tspl3).

gary7 June 30, 2010 23:43

Thank you so much dmoroian, I really appreciate your help.

gary7 July 1, 2010 22:46

Hi dmoroian, now with the info you gave I can read the profile into a variable, for storing each part of the profile which is actually a "list" I tried defining new variables using "rp-var-define" and use "rpvarset" so I can save each part of the profile list in a new variable (e.g. positions: x, y, z and velocities: u, v, w ....). Now for example x is a list which contains x-coordinates of the points in profile...
As an example I defined a profile file as:

Code:

((tes point 4)
(x
  4.00000E+00  4.00000E+00  4.00000E+00  4.00000E+00)
(y
  3.00000E+00  3.00000E+00  3.00000E+00  3.00000E+00)
(z
  2.00000E+00  2.00000E+00  2.00000E+00  2.00000E+00) 
(u
  5.00000E+00  5.00000E+00  5.00000E+00  5.00000E+00)
(v
  6.00000E+00  6.00000E+00  6.00000E+00  6.00000E+00)
(w
  7.00000E+00  7.00000E+00  7.00000E+00  7.00000E+00)
)

when I load the scheme file for the first time I get following error:

Error: %prf-set-var: invalid flonum
Error Object: (4 4 4 4)
--> (these are the values of the first variable list x )

if I load the scheme file for the second time I get:

Error: %prf-set-var: invalid flonum
Error Object: (3 3 3 3)

I get this error up to loading the scheme file for the 6th time(which is the last variable in the list):

Error: %prf-set-var: invalid flonum
Error Object: (7 7 7 7)

But loading more than 6 times gives no more error and everything seems to be fine?!!! and when I check the variables with "rp-var-object" it gives the correct list for each variable.
Now my questions are:
1. Do you know what that error is and is that important?
2. Why after loading the scheme file up to the number of defined variables it no more generates that error?
3. Now that I have extracted each variable in a separate list! is that possible to read them in an array in UDF?

I appreciate your help in advance.

dmoroian July 2, 2010 03:13

1. Well, you define a list of 4 elements but put 5 into it (x 4 4 4 4), and you get an error! No surprize here :)
I suspect that fluent will consider only the last 4 elements (due to the declared length of 4), so for instance the first list will be (4 4 4 4) instead of (x 4 4 4 4), and the same for the rest.
2. I'm not sure what you mean by "...after loading the scheme file..." (I suspect you read the profile and not interpret the scheme file), but my guess is that once fluent allocates the memory for all the declared objects, there is no more problem from its point of view.
3. As far as I know, there is no documented function that reads a list from RP variables, although there are few RP_Get_List_* functions in the var.h header. On top of that, your approach seems a bit peculiar, why do you need to read the list using the scheme environment whereas you need it in the udf? Why not reading it directly from the udf? The profile, is a simple text file, you can parse it accordingly.

gary7 July 2, 2010 13:51

1. No I don't put 5 into it because I use, for example,
(rpsetvar 'x (cdr (list-ref cucu 1))) --> (cucu is based on the naming that you used)

which automatically disregard the first element of the list with the "cdr".

2. By loading the scheme file I mean that after preparing the scheme in a text editor and saving with a *.scm, I go to fluent: File->Read->Scheme to load the scheme that I've developed, but I have to do this more than 6 times to get no more error as I mentioned before.

3.I thought Since profile is in scheme format, it'll easier to read it through scheme script and extracting its data . However, I have no idea how to extract the required data (x, y, z, u, v, w, ...) from a profile file in UDF because it also has other unwanted data as, parentheses, variable names,.... How I can just extract the variable values and store them in an array in UDF? (maybe that's a bit C programming question which I'm not an expert in it because I've used Fortran for my coding stuff :)).

dmoroian July 2, 2010 15:53

Ok, so beside the "tes" profile file, you wrote a scheme script that reads the profile and puts some of the objects into rp variables.
It would be very helpful if you post your scheme code. However, I still think it would be much easier to write your on udf to read in the profile. If you disregard the pointers, C is very much like FORTRAN.

gary7 July 2, 2010 16:34

1. This is the scheme body that I've developed:

Code:

(define cucu (open-input-file "BProfile.prof"))
(define bubu (read cucu))
(close-input-port cucu)
(if (not (rp-var-object 'bc/np))
(rp-var-define 'bc/np 0 'integer #f))
(if (not (rp-var-object 'bc/x))
(rp-var-define 'bc/x 0 'real #f))
(if (not (rp-var-object 'bc/y))
(rp-var-define 'bc/y 0 'real #f))
(if (not (rp-var-object 'bc/z))
(rp-var-define 'bc/z 0 'real #f))
(if (not (rp-var-object 'bc/u))
(rp-var-define 'bc/u 0 'real #f))
(if (not (rp-var-object 'bc/v))
(rp-var-define 'bc/v 0 'real #f))
(if (not (rp-var-object 'bc/w))
(rp-var-define 'bc/w 0 'real #f))

(rpsetvar 'bc/np (list-ref (list-ref md 0) 2))
(rpsetvar 'bc/x (cdr (list-ref bubu 1)))
(rpsetvar 'bc/y (cdr (list-ref bubu 2)))
(rpsetvar 'bc/z (cdr (list-ref bubu 3)))
(rpsetvar 'bc/u (cdr (list-ref bubu 4)))
(rpsetvar 'bc/v (cdr (list-ref bubu 5)))
(rpsetvar 'bc/w (cdr (list-ref bubu 6)))

do yo know why that error message is generated? and is that possible to read these lists (bc/x, bc/y, ....) into arrays in UDF?

2. Can you tell me how I can read in just the profile values (not parentheses and names) into UDF? I know about fscanf but I don't know how to read just the numbers!

dmoroian July 3, 2010 05:06

1. You have to be a bit more organized (let other benefit from your experience, too). Your script shouldn't work since variable md is not defined. However, your error seems to be produced by the fact that you define 'real' variables and assign 'list' to them.
In any case, check what are the values contained in your variables 'bc/x for instance, and see if they are correct
Code:

%rpgetvar 'bc/x
2.
Code:

FILE *pf;
char *buff, *p, name[255], point[255];
long int dim;
int objDim;

if(NULL == (pf = fopen("BProfile.prof","r")))
  Error("Could not open the profile for reading!\n");
fseek(pf,0L,SEEK_END);
dim = ftell(pf);
fclose(pf);

if(NULL == (buff = (char*) calloc(dim,sizeof(char))))
  Error("Could not allocate the buffer!\n");

if(NULL == (pf = fopen("BProfile.prof","r")))
  Error("Could not open the profile for reading!\n");
fread(buff,sizeof(char),dim,pf);
fclose(pf);

p = strstr(buff,"(");
p++;
p = strstr(p,"(");
p++;
sscanf(p,"%s %s %d",name,point,&objDim);/*this should put in variable
                                                            name value "tes", in point
                                                            value "point", and in objDim
                                                            value 4*/

You'll get the picture from here.

gary7 July 4, 2010 02:10

Oh I'm sorry that was a typo because of copy and pasting I corrected the variable name. Is that possible to define a list also?

dmoroian July 5, 2010 11:35

This is just a wild guess, since I've never used it, but try:
Code:

...
(if (not (rp-var-object 'bc/x))
(rp-var-define 'bc/x (cdr (list-ref bubu 1)) 'list #f)
...


gary7 July 6, 2010 17:45

Hi dmoroian, I appreciate all your help, I applied your suggestion of defining a 'list' instead of 'real' and it's working fine :)

gary7 July 8, 2010 18:16

Hi, I'm trying to see how to compile a C++ program using udf in Fluent. I'm trying to add my very simple developed code to Fluent...

  • First of all I found out that I have to use Fluent DEFINE macros in order to the code be complied by Fluent, is that right?
  • Second, when I use C++ instead of C, I'll get the error that:
The system cannot find the file specified.

knowing that, the c++ code is in my working directory and I've run the Fluent from MSVS command prompt. Would you please tell me how to make the code complied in Fluent, here is my sample code, (it's not intended to do anything special I'm just trying to figure out what is going on...):

Code:

#include <iostream>
#include "udf.h"
using namespace std;

int main()
{
    cout << "Test is OK!\n";

    return 0;
}
DEFINE_DELTAT(mydeltat,d)
{
double time_step;
double flow_time = CURRENT_TIME;
if (flow_time < 2.2e-10)
time_step = 2.2e-12;
else
time_step = 2.2e-3;
return time_step;
}

I highly appreciate any help.

dmoroian July 9, 2010 03:45

1. Fluent udf's must be written in C not C++.
2. You have to create a library not a stand alone program, which means, among other things, that you cannot include a "main" function in your library, otherwise it will conflict with fluent's "main" function.
An example of your udf, that is syntacticaly working is:
Code:

#include "udf.h"
DEFINE_DELTAT(mydeltat,d)
{
  real time_step;
  real flow_time = CURRENT_TIME;
  if (flow_time < 2.2e-10)
      time_step = 2.2e-12;
  else
      time_step = 2.2e-3;
 
  return time_step;
}


gary7 July 9, 2010 18:24

Thanks dmoroian, I really appreciate your inputs. The problem that I had with reading a profile which I somehow was able to solve with your suggestions now I'm trying to develop a UDF which applies these entered values from profile on BC which is doable by using DEFINE_PROFILE, however, after running the simulation for a specific time steps, say 10 time steps, I need to read a new profile file and put its values on BC (replace the previous BC values) and continue the simulation again...Do you have any suggestion?
I'm trying to use DEFINE_EXECUTE_AT_END but I don't know if it is possible to set it to be executed at the end of each 10 time steps or it is just executed at the end of every time steps?
Can I tell that to set the new BC and restart the simulation?

I appreciate any help.

dmoroian July 10, 2010 07:37

DEFINE_EXECUTE_AT_END will be executed every iteration or time step (depending on the steady/unsteady calculation).
Why don't you check inside if the iteration is multiple of 10, and if it is, then read a new file, otherwise do something else?

gary7 July 10, 2010 12:12

Ok thanks, I'll try that. What about the first part of my question: reading the new profile again and continuing the simulation with new BC, is that possible to tell the DEFINE_EXECUTE_AT_END to set the new BC and continue simulation?

dmoroian July 12, 2010 15:03

I think that rp variables are available for the udf once per session. That means, if you change an rp variable using your scheme script, the change will not be seen by your udf unless you make a save and read case in between:
- read profile
- set the rp variables
- save case
- read case
- now the new values of the rp variables are available for the udf
If you want to do this every 10 time steps, then you have to check that in your scheme script and do the above steps every 10 time steps. But in my opinion this is totally opposite to an efficient algorithm.

gary7 July 12, 2010 16:08

I really respect your time and appreciate it... after reading profile and setting the rp variables then I read the variables in a UDF with DEFINE_PROFILE to set the BC condition, after doing simulation for N time steps then how I can specify in EXECUTE_AT_END to reset the BC again and continue the simulation (assuming that I've done saving and reading the case in prior)?
In other words, how can I recall the DEFINE_PROFILE UDF again and again in the EXECUTE_AT_END and continue simulation after that? is that possible?

dmoroian July 13, 2010 08:29

Your questions are still confusing me, so please make a simple and clear list with your problem.
This is what I understood until now:
1. You want to read a fluent profile from a file. For this purpose you use a scheme script. You can add this scheme script in "Execute Commands", and automaticaly executed every time step or ...10 time steps.
2. You want to set some variables from the profile into rp variables. For this you use a scheme script (maybe the same as in step 1).
3. You want to access the rp variables from inside the solver. For this you use a udf DEFINE_PROFILE, and attach this udf to a surface as a boundary condition. This boundary condition will be used by the solver every iteration (wether you want it or not).
4. Every 10 time steps you want to change the values of the rp variables with a new profile. For this purpose, you try to use EXECUTE_AT_END? I suggest a simpler way: see step 1.

gary7 July 13, 2010 12:51

Here is a clarification to the first and 4th steps which I'm trying to figure out:

After running the simulation for 10 time steps I need to check if the new profile file is ready to be used or not (the profile is provided by another simulation which I don't know how much time it takes to be ready) so my simulation should be in standby mode till that file becomes ready. I was trying to do this waiting through DEFINE_EXECUTE_AT_END in which after 10 time steps check for that file and stands till that file becomes ready...After the file was provided the steps I need to read this new file and set it as new BC. It means I need to go back to step 1 and repeat the process again and again.
1. Is that possible to go back to step 1 (reading the scheme file again) and resetting the rp variables and BC again in DEFINE_EXECUTE_AT_END macro? how?

2. If the answer to question 1 is No then do I need to read the profile file in a UDF instead of a scheme? in order to just dealing with UDFs?

Thank you in advance for your time and consideration,

dmoroian July 13, 2010 16:35

1. No it is not.
2. Yes, my choice for this case would be to do everything inside a udf.

gary7 July 13, 2010 18:32

Ok then, I need to input required BC variables through UDF...then it'd be better to use a simple data file not a profile file format so it can be easily read and written...to have a clue about the face centers of the problem on the intended boundary I tried writing out the BC face centroids using the exact same example as in UDF manual (second example in section 3.2.6) here is what I input as a UDF:

Code:

#include "udf.h"

FILE *fout;

void Print_Thread_Face_Centroids(Domain *domain, int id)
{
    real FC[2];
    face_t f;
    int n_faces,j;
    Thread *t = Lookup_Thread(domain, id);
   
    n_faces=THREAD_N_ELEMENTS_INT(t);
    fprintf(fout,"%d\n", n_faces);
    j=0;
    begin_f_loop(f,t)
{
    F_CENTROID(FC,f,t);
    j++;
    fprintf(fout, "f%d %g %g %g %d\n", f, FC[0], FC[1], FC[2], j));
}
    end_f_loop(f,t)
    fprintf(fout, "\n");
}

DEFINE_ON_DEMAND(get_coord)
{
    Domain *domain;
    domain = Get_Domain(1);
    fout = fopen("BCData.txt", "w");
    Print_Thread_Face_Centroids(domain, 7);
    fclose(fout);
}

when I run this UDF at demand what I get in the output file "BCData.txt" is just:

Code:

2500
f1050120822 3.51252e-007 0 3.51252e-007 1

since my flow field is a cubic with 50 cells in x and z direction and 10 cells in y direction, the boundary with ID=7 is one of the y-planes and its a wall. So 2500 which is the number of faces on this boundary is OK but I don't understand why begin_f_loop is being done just once instead of 2500 times?!!! if I don't use f_loop I'll get the same result so the loop is actually doing nothing!!!!

And if I use the same procedure but instead of DEFINE_ON_DEMAND use DEFINE_EXECUTE_AT_END the code will be trapped in f_loop forever?????!!!!!!!!!!

Thanks,

gary7 July 14, 2010 14:42

OK, After a long time on it I found the problem...it was because of the defining FC[2] in the 3D model...:rolleyes:

gary7 July 15, 2010 02:37

Ok, I'm doing all the things in a UDF now as you suggested. Now, the only thing is that when in DEFINE_EXECUTE_AT_END I read the new BC data file how can I reset the new BC from there and continue the simulation...
Any idea is highly appreciated.

dmoroian July 15, 2010 03:23

DEFINE_EXECUTE_AT_END cannot directly reset your boundary conditions, for this purpose fluent provides you with a macro called DEFINE_PROFILE. You have to present a bit more detailed what you do.

gary7 July 15, 2010 11:18

I need to set a new BC in my simulation every time a new BC data which is provided from outside is ready, that is I first run the simulation with a specified BC for 10 time step then in EXECUTE_AT_END I check for the availability of the new BC data file upon its availability I need to reset the boundary condition with this new file and continue the simulation (if the BC data file is not still ready the simulation will be in standby mode in there checking continuously for the file till it becomes ready) ...
I know about setting boundary with DEFINE_PROFILE macro my problem is that I need to call this macro repeatedly after checking and approving the existence of the new BC data file in EXECUTE_AT_END.

dmoroian July 16, 2010 05:16

None of the DEFINE_* macros that fluent provides for you are designed to be called by you, but by fluent it self. Consequently, you cannot call any of them.
Here I think I see a missunderstanding. You don't need to call any of the DEFINE_* macros, they are called periodically by fluent, any way (excepting DEFINE_ON_DEMAND).
The simplest way would be to do the checking and reading directly inside DEFINE_PROFILE (which is called by fluent at least every iteration). The input files are small and it doesn't take that much time to read it (when the check says you have to read it).
If you insist to use DEFINE_EXECUTE_AT_END, then you need to use global defined arrays. You will use those arrays to access the data read within DEFINE_EXECUTE_AT_END from DEFINE_PROFILE.

gary7 July 18, 2010 02:32

Thanks Dmoroian, yeah it seems that DEFINE_PROFILE is called at beginning of every time step I thought it is just called once in the beginning of the simulation...

engin June 7, 2011 08:44

UDF profile read question
 
Hi,

I am working with FLUENT 6.3.26 and I am having difficulties in reading a profile file into UDF later to be used as boundary conditions. My question is that can I assign values to a 1D array if I am working with interpreted UDF?

Thanks in advance

Abhijeeth July 12, 2022 02:17

Quote:

Originally Posted by dmoroian (Post 265362)
1. Well, you define a list of 4 elements but put 5 into it (x 4 4 4 4), and you get an error! No surprize here :)
I suspect that fluent will consider only the last 4 elements (due to the declared length of 4), so for instance the first list will be (4 4 4 4) instead of (x 4 4 4 4), and the same for the rest.
2. I'm not sure what you mean by "...after loading the scheme file..." (I suspect you read the profile and not interpret the scheme file), but my guess is that once fluent allocates the memory for all the declared objects, there is no more problem from its point of view.
3. As far as I know, there is no documented function that reads a list from RP variables, although there are few RP_Get_List_* functions in the var.h header. On top of that, your approach seems a bit peculiar, why do you need to read the list using the scheme environment whereas you need it in the udf? Why not reading it directly from the udf? The profile, is a simple text file, you can parse it accordingly.

Can u share the code statement lines for extracting values from UDF_PROFILE function in the list form or
how to directly extract and use the value in the fomula.


All times are GMT -4. The time now is 17:30.