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/)
-   -   Porosity Variation with Time (https://www.cfd-online.com/Forums/fluent-udf/172803-porosity-variation-time.html)

Baden June 6, 2016 13:09

Porosity Variation with Time
 
Hello everyone,

I am a college student trying to model the flow of acid through a porous rock sample. After some research, I have come to the conclusion that I need to write a UDF for the change in porosity as a function of time due to the acid reacting with the rock.

From what I understand, I need to use the DEFINE_PROFILE macro. Inside the macro, I need to loop over each of the cells to define the new porosity at each new time. For the sake of simplicity, the porosity formula (of the solid) I will be using is as follows:

Quote:

http://i.imgur.com/Yolmp4p.png
  • φ is the new porosity
  • X is a constant
  • Δt is the change in time
  • φ_0 is the old porosity

I have two questions.
  1. How do I define an initial porosity that isn't constant across all cells, since I want a random porosity distribution?
  2. How do I store the "new" value of porosity for each cell so that it can be accessed and used as the "old" porosity for the next calculation? I know that a C_POR function exists, but will I assumed it only pulled the initial porosity.
Below I've included a skeleton of the what I have come up with so far. Any help would be greatly appreciated as I have scoured the internet and come up empty handed. I did find some useful information in this thread, but nothing that answers my questions.

Code:

#include "udf.h"

DEFINE_PROFILE(porosity_variation,t,i)
{
    real delta_t = CURRENT_TIMESTEP; /* not sure if this should be PREVIOUS_TIMESTEP instead */
    real X = 1.0; /* this is an arbitrary value */
    cell_t c;
   
    begin_c_loop(c,t)
        {
            C_PROFILE(c,t,i) = 1 - (X * delta_t - phi_0 ^ 2 + phi_0) / (X * delta_t - phi_0 + 1);
        }
    end_c_loop(c,t)
}


Bruno Machado June 7, 2016 05:52

Quote:

Originally Posted by Baden (Post 603599)
Hello everyone,
  1. How do I define an initial porosity that isn't constant across all cells, since I want a random porosity distribution?

you can add #include <stdlib.h> and use the function randomize() to generate a random number to you.
Quote:

  1. How do I store the "new" value of porosity for each cell so that it can be accessed and used as the "old" porosity for the next calculation? I know that a C_POR function exists, but will I assumed it only pulled the initial porosity.

you can storage the value of the porosity in a UDMI at the end of each iteration using the macro DEFINE_AT_THE_END.

Baden June 7, 2016 10:13

Thank you so much for the response.

Quote:

Originally Posted by Bruno Machado (Post 603693)
you can add #include <stdlib.h> and use the function randomize() to generate a random number to you.

To expand on this, would I include the initial porosity generation inside the same UDF as my porosity variation with time? If not, where would be the appropriate place to hook these two UDFs?

Quote:

Originally Posted by Bruno Machado (Post 603693)
you can storage the value of the porosity in a UDMI at the end of each iteration using the macro DEFINE_AT_THE_END.

Are you referring the the DEFINE_EXECUTE_AT_END macro? If so, would you mind explaining how you intended it to be used? I've read through this page and don't quite understand it's use in my application.

Bruno Machado June 7, 2016 11:17

Quote:

Originally Posted by Baden (Post 603735)
Thank you so much for the response.


To expand on this, would I include the initial porosity generation inside the same UDF as my porosity variation with time? If not, where would be the appropriate place to hook these two UDFs?


Are you referring the the DEFINE_EXECUTE_AT_END macro? If so, would you mind explaining how you intended it to be used? I've read through this page and don't quite understand it's use in my application.

1) you can use the function to generate a random number. multiply it to the porosity in the cell and it should give you a "non uniform" porosity. just be careful, because if it varies too much, lets say porosity between 0.1 and 0.9, it can lead to divergence problems.

2) yes, my mistake, typed it quickly and did not check the right macro. the DEFINE_EXECUTE_AT_END executes a command at the end of each iteration. what you can do is an if statement that storage the value of porosity in the UDMI with dependence in a relation of time and current time step.

Baden June 7, 2016 13:06

Quote:

Originally Posted by Bruno Machado (Post 603745)
2) yes, my mistake, typed it quickly and did not check the right macro. the DEFINE_EXECUTE_AT_END executes a command at the end of each iteration. what you can do is an if statement that storage the value of porosity in the UDMI with dependence in a relation of time and current time step.

I am still struggling to understand how to achieve the time variation. Since the variable I'm using is native to Fluent (porosity), is there not a way to call it without using UDM? The only example I could find of what you are describing is in this thread and it doesn't provide an example of the "if statement" one would have to use to only run at the end of a timestep for steady-state flow.

I'm relatively new to Fluent and there aren't many examples on the internet of what I'm trying to do so I'm having a hard time following. Is there a chance you could post a sample UDF code or a modification to the code I wrote to demonstrate how I would make the porosity dependent on time?

Again, I really appreciate you taking the time to answer my questions.

Baden June 7, 2016 17:16

Here is an update of the code I have so far, which is based on this thread.

Code:

#include "udf.h"

DEFINE_PROFILE(porosity_variation,t,i)
{
    real X = 1; /* arbitrary constant */
    real delta_t = CURRENT_TIMESTEP;
    cell_t c;
   
    begin_c_loop(c,t)
    {
        if (N_TIME == 1)
        {
            C_PROFILE(c,t,i) = 0.8;
        }
        else
        {
            real phi_0 = C_UDMI(c,t,0);
            C_PROFILE(c,t,i) = 1 - (-(phi_0 * phi_0) + phi_0 + X * delta_t) / (-phi_0 + X * delta_t + 1);
        }
        C_UDMI(c,t,0) = C_PROFILE(c,t,i);
    }
    end_c_loop(c,t)
}

I'm not quite sure if it will do what I want it to do, so any input is welcome. I've set the initial porosity to be a constant 0.8 for all cells (or at least that's what I intended it to do) so I could tackle one problem at a time.

Bruno Machado June 8, 2016 04:40

Quote:

Originally Posted by Baden (Post 603781)
Here is an update of the code I have so far, which is based on this thread.

I'm not quite sure if it will do what I want it to do, so any input is welcome. I've set the initial porosity to be a constant 0.8 for all cells (or at least that's what I intended it to do) so I could tackle one problem at a time.

did you try to compile and run?

just couple of things. instead of using "1", use "1.0". I spent over a month trying to find a bug in my code and it was that the compiler was messing with a number because of the decimal place.

and you have to initialize your UDMI, otherwise phi_0 has no value. You can initialize it in you initialization process as 0.8 and then use it like this.

Code:

#include "udf.h"

DEFINE_PROFILE(porosity_variation,t,i)
{
real X = 1.0; /* arbitrary constant */
real delta_t = CURRENT_TIMESTEP;
cell_t c;

begin_c_loop(c,t)
{
if (N_TIME == 1)
{
C_PROFILE(c,t,i) = C_UDMI(c,t,0);
}
else
{
real phi_0 = C_UDMI(c,t,0);
C_PROFILE(c,t,i) = 1.0 - (-(phi_0 * phi_0) + phi_0 + X * delta_t) / (-phi_0 + X * delta_t + 1.0);
}
C_UDMI(c,t,0) = C_PROFILE(c,t,i);
}
end_c_loop(c,t)
}


Baden June 8, 2016 12:45

Quote:

Originally Posted by Bruno Machado (Post 603859)
did you try to compile and run?

just couple of things. instead of using "1", use "1.0". I spent over a month trying to find a bug in my code and it was that the compiler was messing with a number because of the decimal place.

and you have to initialize your UDMI, otherwise phi_0 has no value. You can initialize it in you initialization process as 0.8 and then use it like this.

I made the suggested changes as well as attempted to add a macro to initialize the UDMI:

Code:

#include "udf.h"

DEFINE_PROFILE(porosity_variation,t,i)
{
    real X = 1.0;
    real delta_t = CURRENT_TIMESTEP;
    cell_t c;
   
    begin_c_loop(c,t)
    {
        if (N_TIME == 1)
        {
            C_PROFILE(c,t,i) = C_UDMI(c,t,0);
        }
        else
        {
            real phi_0 = C_UDMI(c,t,0);
            C_PROFILE(c,t,i) = 1.0 - (-(phi_0 * phi_0) + phi_0 + X * delta_t) / (-phi_0 + X * delta_t + 1.0);
        }
        C_UDMI(c,t,0) = C_PROFILE(c,t,i);
    }
    end_c_loop(c,t)
}

DEFINE_INIT(UDMI0_init,d)
{
    Thread *t;
    cell_t c;
    Thread *t_fluid = Lookup_Thread(d,3); /* 3 is the ID of the fluid */
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                C_UDMI(c,t,0) = 0.8;
            }
            end_c_loop(c,t)
        }
    }
}

I interpreted the code and ran it, however, either I did the setup incorrectly or the code is not correct seeing as the porosity values did not appear to change. I have a feeling that the initialization code is wildly incorrect, but it is the best I could figure out.

http://i.imgur.com/UA9GTHw.png



Also, earlier you said:

Quote:

Originally Posted by Bruno Machado (Post 603745)
2) yes, my mistake, typed it quickly and did not check the right macro. the DEFINE_EXECUTE_AT_END executes a command at the end of each iteration. what you can do is an if statement that storage the value of porosity in the UDMI with dependence in a relation of time and current time step.

Since my code is not doing this, could the lack of change in porosity be caused by storing the previous UDMI value for each iteration rather than each timestep? I attempted to use the DEFINE_EXECUTE_AT_END macro, but I couldn't figure out how to only run it at the end of each timestep since I'm doing steady-state.http://www.cfd-online.com/Forums/dat...AAAElFTkSuQmCC

Bruno Machado June 9, 2016 04:25

Quote:

Originally Posted by Baden (Post 603976)
I made the suggested changes as well as attempted to add a macro to initialize the UDMI:

Code:

#include "udf.h"

DEFINE_PROFILE(porosity_variation,t,i)
{
    real X = 1.0;
    real delta_t = CURRENT_TIMESTEP;
    cell_t c;
   
    begin_c_loop(c,t)
    {
        if (N_TIME == 1)
        {
            C_PROFILE(c,t,i) = C_UDMI(c,t,0);
        }
        else
        {
            real phi_0 = C_UDMI(c,t,0);
            C_PROFILE(c,t,i) = 1.0 - (-(phi_0 * phi_0) + phi_0 + X * delta_t) / (-phi_0 + X * delta_t + 1.0);
        }
        C_UDMI(c,t,0) = C_PROFILE(c,t,i);
    }
    end_c_loop(c,t)
}

DEFINE_INIT(UDMI0_init,d)
{
    Thread *t;
    cell_t c;
    Thread *t_fluid = Lookup_Thread(d,3); /* 3 is the ID of the fluid */
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                C_UDMI(c,t,0) = 0.8;
            }
            end_c_loop(c,t)
        }
    }
}

I interpreted the code and ran it, however, either I did the setup incorrectly or the code is not correct seeing as the porosity values did not appear to change. I have a feeling that the initialization code is wildly incorrect, but it is the best I could figure out.

http://i.imgur.com/UA9GTHw.png



Also, earlier you said:


Since my code is not doing this, could the lack of change in porosity be caused by storing the previous UDMI value for each iteration rather than each timestep? I attempted to use the DEFINE_EXECUTE_AT_END macro, but I couldn't figure out how to only run it at the end of each timestep since I'm doing steady-state.http://www.cfd-online.com/Forums/dat...AAAElFTkSuQmCC

I am not sure how the time step macros work, but instead of using (N_TIME == 1) try to do an if with an increment in a integer and see if it varies as you expect. then you can check rather the problem is in the loop or in the if statements.

"DEFINE_EXECUTE_AT_END is a general purpose macro that is executed at the end of an iteration in a steady state run, or at the end of a time step in a transient run.". It runs automatically at the end of each iteration/time step for stead-state/transient case. Did you hook it properly?

Baden June 9, 2016 14:19

Quote:

Originally Posted by Bruno Machado (Post 604029)
I am not sure how the time step macros work, but instead of using (N_TIME == 1) try to do an if with an increment in a integer and see if it varies as you expect. then you can check rather the problem is in the loop or in the if statements.

"DEFINE_EXECUTE_AT_END is a general purpose macro that is executed at the end of an iteration in a steady state run, or at the end of a time step in a transient run.". It runs automatically at the end of each iteration/time step for stead-state/transient case. Did you hook it properly?

Due to my lack of knowledge of UDFs, I don't quite understand. Please forgive my lack of knowledge as my understanding of UDFs is limited to the user manual and the information that you have provided.

Let me outline what I think I need to do. Please correct me if I'm wrong.
  1. use a DEFINE_INIT macro to set the initial the values of porosity
  2. use a DEFINE_PROFILE macro to change the porosity profile as a function of time and previous porosity
  3. use UDMI to store the value of previous porosity for each cell so it can be called in the next iteration
  4. use a DEFINE_EXECUTE_AT_END macro to store the calculated value of porosity in the UDMI at the end of each iteration
  5. add an if statement to the DEFINE_EXECUTE_AT_END macro to make it only run per timestep rather than per iteration (I'm not sure about this step, but it seems to be what was suggested here)

Bruno Machado June 10, 2016 04:10

Quote:

Originally Posted by Baden (Post 604167)
Due to my lack of knowledge of UDFs, I don't quite understand. Please forgive my lack of knowledge as my understanding of UDFs is limited to the user manual and the information that you have provided.

Let me outline what I think I need to do. Please correct me if I'm wrong.
  1. use a DEFINE_INIT macro to set the initial the values of porosity
  2. use a DEFINE_PROFILE macro to change the porosity profile as a function of time and previous porosity
  3. use UDMI to store the value of previous porosity for each cell so it can be called in the next iteration
  4. use a DEFINE_EXECUTE_AT_END macro to store the calculated value of porosity in the UDMI at the end of each iteration
  5. add an if statement to the DEFINE_EXECUTE_AT_END macro to make it only run per timestep rather than per iteration (I'm not sure about this step, but it seems to be what was suggested here)

you are mostly right. in the 5th step, looks like you don't need to add any if condition to run it to each time step, once it does like that automatically. have a look at its definition in the manual:

Quote:

DEFINE_EXECUTE_AT_END is a general purpose macro that is executed at the end of an iteration in a steady state run, or at the end of a time step in a transient run.
http://jullio.pe.kr/fluent6.1/help/html/udf/node55.htm

In other words, it wont compute anything in the DEFINE_AT_THE_END unless at the end of the time step for transient cases.

Baden June 10, 2016 10:25

Quote:

Originally Posted by Bruno Machado (Post 604239)
you are mostly right. in the 5th step, looks like you don't need to add any if condition to run it to each time step, once it does like that automatically. have a look at its definition in the manual:



http://jullio.pe.kr/fluent6.1/help/html/udf/node55.htm

In other words, it wont compute anything in the DEFINE_AT_THE_END unless at the end of the time step for transient cases.

Right, however, I am running my simulation as steady-state. So from what I understand, I need an if statement to make it only run at the end of a timestep?

Bruno Machado June 10, 2016 10:32

Quote:

Originally Posted by Baden (Post 604311)
Right, however, I am running my simulation as steady-state. So from what I understand, I need an if statement to make it only run at the end of a timestep?

but if you are running it stead-state, there is no time step...

Baden June 10, 2016 10:42

Quote:

Originally Posted by Bruno Machado (Post 604312)
but if you are running it stead-state, there is no time step...

I feel like and idiot. I did not know this.

So how would I model a change in porosity as a function of time if there isn't a timestep? Is there another way to get change in time other than this?

Code:

real dt = CURRENT_TIMESTEP;

Bruno Machado June 10, 2016 10:50

Quote:

Originally Posted by Baden (Post 604315)
I feel like and idiot. I did not know this.

So how would I model a change in porosity as a function of time if there isn't a timestep? Is there another way to get change in time other than this?

Code:

real dt = CURRENT_TIMESTEP;

the steady state solution is the one when time is equal to infinity, in other words, it wont change anymore. If you want it to vary on time, you need to run a transient solution.

This macro is for transient case, which is the way you gotta run your case if you want time variation on it. Have a look about the transient problem in the manual and you can also have a look in youtube, there are many videos of time dependent variation.

Baden June 10, 2016 10:52

Quote:

Originally Posted by Bruno Machado (Post 604316)
the steady state solution is the one when time is equal to infinity, in other words, it wont change anymore. If you want it to vary on time, you need to run a transient solution.

This macro is for transient case, which is the way you gotta run your case if you want time variation on it. Have a look about the transient problem in the manual and you can also have a look in youtube, there are many videos of time dependent variation.

Alright, I will. I didn't realize I would have to run it as transient since my flow rate is steady-state. Much appreciated.

I will report back if I encounter any more problems.

Baden June 10, 2016 13:56

I do have one question about the DEFINE_EXECUTE_AT_END macro.

I'm trying to store the calculated value of porosity in the UDMI using the DEFINE_EXECUTE_AT_END macro but I'm not quite sure how to reference the porosity since the C_PROFILE macro requires an index (i).

Code:

#define ID 3.0 /* ID of the fluid */

DEFINE_EXECUTE_AT_END(execute_at_end)
{
    Domain *d;
    Thread *t;
    Thread *t_fluid = Lookup_Thread(d,ID);
    cell_t c;
    d = Get_Domain(1);    /* mixture domain if multiphase */
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                C_UDMI(c,t,0) = C_PROFILE(c,t,???)
            }
            end_c_loop(c,t)
        }
    }
}

I guess my question is how do I pull the index for the porosity variable so I can reference it?

Bruno Machado June 10, 2016 15:47

Quote:

Originally Posted by Baden (Post 604336)
I do have one question about the DEFINE_EXECUTE_AT_END macro.

I'm trying to store the calculated value of porosity in the UDMI using the DEFINE_EXECUTE_AT_END macro but I'm not quite sure how to reference the porosity since the C_PROFILE macro requires an index (i).

Code:

#define ID 3.0 /* ID of the fluid */

DEFINE_EXECUTE_AT_END(execute_at_end)
{
    Domain *d;
    Thread *t;
    Thread *t_fluid = Lookup_Thread(d,ID);
    cell_t c;
    d = Get_Domain(1);    /* mixture domain if multiphase */
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                C_UDMI(c,t,0) = C_PROFILE(c,t,???)
            }
            end_c_loop(c,t)
        }
    }
}

I guess my question is how do I pull the index for the porosity variable so I can reference it?

I wrote what I think will work for you. I did not compile, so might have some mistakes. The logic is explained in the code. Hope it clarifies things to you.

Code:

#include "udf.h"

#define ID 3.0 /* ID of the fluid */

/* in this part, the value of the porosity is initialised as 0.8 */
DEFINE_INIT(UDMI0_init,d)
{
    Thread *t;
    cell_t c;
    Thread *t_fluid = Lookup_Thread(d,3); /* 3 is the ID of the fluid */
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                C_UDMI(c,t,0) = 0.8;
            }
            end_c_loop(c,t)
        }
    }
}

/* this macro will read the value of the UDMI_0. For the first time step, it will be 0.8,
after that, it will use the value of the UDMI_0 calculated in the DEFINE_EXECUTE_AT_END */

DEFINE_PROFILE(porosity_variation,t,i)
{

    cell_t c;
   
    begin_c_loop(c,t)
    {
                C_PROFILE(c,t,i) = C_UDMI(c,t,0);
    }
    end_c_loop(c,t)
}


/*Since this macro is only executed at the end of each time step, there is no need to an IF statement.
This command will define that phi_0 is the value of the old porosity, then the porosity_new can be solved and followed by the definition of the new value of the UDMI_0.
This value will be read by the DEFINE_PROFILE as the new value of the porosity at the end of each time step*/

DEFINE_EXECUTE_AT_END(execute_at_end)
{
    Domain *d;
    Thread *t;
    Thread *t_fluid = Lookup_Thread(d,ID);
    cell_t c;
    d = Get_Domain(1);    /* mixture domain if multiphase */
    real porosity;
    real X = 1.0; /* arbitrary constant */
    real delta_t = CURRENT_TIMESTEP;
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                            real phi_0 = C_UDMI(c,t,0);
                      porosity_new = 1.0 - (-(phi_0 * phi_0) + phi_0 + X * delta_t) / (-phi_0 + X * delta_t + 1.0);
                                C_UDMI(c,t,0) = porosity_new;
                }
            }
            end_c_loop(c,t)
        }
    }
}


Baden June 10, 2016 17:06

Quote:

Originally Posted by Bruno Machado (Post 604351)
I wrote what I think will work for you. I did not compile, so might have some mistakes. The logic is explained in the code. Hope it clarifies things to you.

Thank you very much. I never thought about calculating the new porosity value in the DEFINE_EXECUTE_AT_END macro as opposed to the DEFINE_PROFILE macro.

I did notice one oddity when interpreting the code (I don't compile it because I've read the manual and still have no idea how to). I received a parse error whenever the "d = Get_Domain(1);" was placed on any line above where it is now in the following code:

Code:

DEFINE_EXECUTE_AT_END(execute_at_end)
{
    Domain *d;
    Thread *t;
    Thread *t_fluid = Lookup_Thread(d,ID);
    cell_t c;
    real X = 1.0;
    real dt = CURRENT_TIMESTEP;
    d = Get_Domain(1);
   
    thread_loop_c(t,d)
    {
        if (t == t_fluid)
        {
            begin_c_loop(c,t)
            {
                real phi_0 = C_UDMI(c,t,0);
                real phi = 1.0 - (-(phi_0 * phi_0) + phi_0 + X * dt) / (-phi_0 + X * dt + 1.0);
                C_UDMI(c,t,0) = phi;
            }
            end_c_loop(c,t)
        }
    }
}


`e` June 10, 2016 17:55

Fluent uses ANSI C which follows a number of strict rules including the requirement of declaring all variables at the beginning of a code block. However, you can declare and initialise the domain thread on one line with:

Code:

Domain *d = Get_Domain(1);


All times are GMT -4. The time now is 23:29.