CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > Software User Forums > ANSYS > FLUENT > Fluent UDF and Scheme Programming

UDF for inlet temperature and species concentration

Register Blogs Community New Posts Updated Threads Search

Like Tree5Likes
  • 5 Post By obscureed

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   February 7, 2018, 12:59
Default UDF for inlet temperature and species concentration
  #1
New Member
 
Haidor
Join Date: May 2017
Posts: 5
Rep Power: 9
haidory is on a distinguished road
Hello,

I modeling a room with multiple inlets and outlets. I want one of my inlets to have the same temperature and species concentration as one of my outlets. I tried the recirculation boundary condition in Fluent but it was causing a problem with species convergence. Can I do this using a UDF? Thank you.
haidory is offline   Reply With Quote

Old   February 7, 2018, 13:05
Default
  #2
New Member
 
Haidor
Join Date: May 2017
Posts: 5
Rep Power: 9
haidory is on a distinguished road
Oh and I am simulating a steady state by the way. Thanks for your help!
haidory is offline   Reply With Quote

Old   February 8, 2018, 04:55
Default
  #3
Senior Member
 
Join Date: Nov 2013
Posts: 1,965
Rep Power: 27
pakk will become famous soon enough
Yes you can.

Code:
DEFINE_PROFILE(inlettemp,c,t,i)
{
face f;
THREAD *outletthread;
real A, area=0,sumtemp=0,temp;

 outletthread = get_thread(12541); /*here put the number of the outlet thread. */
/*And get_thread is the wrong function, find the correct one in help. */

 BEGIN_F_LOOP(outletthread,f) { /*loop through faces of your outlet */
  F_AREA(A,outletthread,f); /*make A the area of the face */
  area += NV_MAG(A);
  sumtemp += F_T(f,outletthread);
 }
 END_F_LOOP(outletthread)

 temp=sumtemp/A;   /* temp becomes the average temperature */

 BEGIN_F_LOOP(c,t) {
   F_PROFILE(c,t)=temp;
 }
 END_F_LOOP(c,t);
}
Above code is surely wrong in grammar (I did it by memory, normally I look up the names), but the logic behind it should work.
pakk is offline   Reply With Quote

Old   February 8, 2018, 12:57
Default
  #4
New Member
 
Haidor
Join Date: May 2017
Posts: 5
Rep Power: 9
haidory is on a distinguished road
Great, thank you very much!
haidory is offline   Reply With Quote

Old   February 12, 2018, 13:55
Default
  #5
Senior Member
 
Join Date: Sep 2017
Posts: 246
Rep Power: 12
obscureed is on a distinguished road
Hi Haidory,

pakk's sketch is one good way. You will need to work through the code line by line to fix the syntax, so (as pakk mentioned) you only have the skeleton of a solution so far. Some hints:
-- "A" needs to be declared as an array "A[ND_ND]"
-- The correct function is "Lookup_Thread(domain, 1234);", so, before that you need "Domain *domain = Get_Domain(1);"
-- Accumulate "sumtemp += F_T(f,outletthread) * NV_MAG(A);"
-- Then outside the loop divide by area, not by A.
-- "begin_f_loop(f,outletthread) { ... } end_f_loop(f,outletthread);"
etc

Then you need similar UDF for each species, except with F_YI(f,outletthread,i) for mass fraction of species i, instead of F_T(f,outletthread). I cannot think of a neat way to do each of the species except to copy-paste-edit a new profile UDF for each one.

I'll suggest a different way in another post.

Good luck!
Ed
obscureed is offline   Reply With Quote

Old   February 12, 2018, 14:03
Default
  #6
Senior Member
 
Join Date: Sep 2017
Posts: 246
Rep Power: 12
obscureed is on a distinguished road
Oh, one more thing which might not be easy to pick out of the manual:
to make that UDF work in parallel, you need something like this, after the first face loop and before you calculate "temp":
Code:
#if RP_NODE
  PRF_GRSUM1(area);
  PRF_GRSUM1(sumtemp);
#endif
obscureed is offline   Reply With Quote

Old   February 12, 2018, 15:08
Default
  #7
Senior Member
 
Join Date: Sep 2017
Posts: 246
Rep Power: 12
obscureed is on a distinguished road
One alternative approach would be to venture into the murky world of Scheme programming in Fluent. This will be a longish post, because I'll work through the steps that I would go through for temperature. The end result is fairly concise but not easy to digest or debug:

First, find the TUI command that sets the boundary condition you want. (This is horribly, horribly model-dependent -- a major disadvantage of this approach.) So, for example, I have in front of me a model with a mass-flow-inlet called "inlet" and a pressure-outlet called "outlet". If I work through the TUI command "/define/boundary-condition/mass-flow-inlet", I see the following input/output:
Code:
/define/boundary-conditions> mass-flow-inlet
(inlet)
zone id/name [inlet] inlet
Reference Frame: Absolute [yes] 
Mass Flow Specification Method: Mass Flow Rate [yes] 
Use Profile for Mass Flow Rate? [no] 
Mass Flow Rate (kg/s) [3.598] 
Use Profile for Total Temperature? [no] 
Total Temperature (k) [300] 400
Use Profile for Supersonic/Initial Gauge Pressure? [no] 
Supersonic/Initial Gauge Pressure (pascal) [0] 
Direction Specification Method: Direction Vector [no] 
Direction Specification Method: Normal to Boundary [yes] 
Turbulent Specification Method: K and Epsilon [no] 
Turbulent Specification Method: Intensity and Length Scale [no] 
Turbulent Specification Method: Intensity and Viscosity Ratio [no] 
Turbulent Specification Method: Intensity and Hydraulic Diameter [yes] 
Turbulent Intensity (%) [5] 
Hydraulic Diameter (m) [0.508]
and hence I conclude that the following command changes the inlet temperature and nothing else:
Code:
/define/boundary-conditions/mass-flow-inlet inlet , , , , , 400 , , , , , , , , , ,
Check that this works. (And adapt it for your own case -- it will be completely different when species are involved. You should probably use a velocity inlet if you can -- it will be more stable. I've provided another example at the end.)

Check it again.

Now, find a Scheme command that creates this text with a numeric input. Here is one:
Code:
(format #f "/define/boundary-conditions/mass-flow-inlet inlet , , , , , ~16.8e , , , , , , , , , ," 395.1)
Next, find a Scheme command that calculates the temperature that you want. For example, if the TUI command "/surface/report/mass-weighted-av (outlet) temperature n" calculates the value that you want, with the answer being the last word of the text output, then this command gets that answer as a real value:
Code:
(pick-a-real "/rep/surf/mwa (outlet) temp n")
By the way, note that I am using mass-weighted averaging here, which is almost certainly the most appropriate method. The UDFs used area-weighted averaging (but you could adapt them using "F_FLUX(f,t)").

Combine those two functions to get the text command that you want:
Code:
(format #f "/define/boundary-conditions/mass-flow-inlet inlet , , , , , ~16.8e , , , , , , , , , ," 
   (pick-a-real "/rep/surf/mwa (outlet) temp n"))
Paste that into the text window and check that it works. Now, wrap that in the Scheme command to run that string as a TUI command:
Code:
(ti-menu-load-string
  (format #f "/define/boundary-conditions/mass-flow-inlet inlet , , , , , ~16.8e , , , , , , , , , ," 
          (pick-a-real "/rep/surf/mwa (outlet) temp n")))
Paste that into the command window, then go and check (by GUI) that it has done exactly what you want. Check again.

While I'm here, I might as well mention that you can adjust the value, once you get your head round the brackets and Reverse-Polish syntax. For example, if your recirculated gas had a temperature loss on its way, you could reduce the temperature that reaches the inlet:
Code:
(let ((temp_loss 5))
  (ti-menu-load-string
    (format #f "/define/boundary-conditions/mass-flow-inlet inlet , , , , , ~16.8e , , , , , , , , , ,"
            (- (pick-a-real "/rep/surf/mwa (outlet) temp n")
               temp_loss))))
I would advise you to put that command into a text file called something like "adjuster.scm". (It will grow to monstrous length when you have multiple species.) Then you can just type the command
Code:
(load "adjuster.scm")
and check that this works.

Finally, you can put that last command into Calculation Activities...Execute Commands, with an instruction to do the adjustment every 10 or 20 iterations. (And, finally, we reach a benefit of doing it by Scheme rather than by UDF.)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

As another example, I've just turned on species with the carbon-monoxide-air template, and made "inlet" into a velocity-inlet. My TUI command is now something like this:
Code:
/define/boundary-conditions/velocity-inlet
 inlet n n y y n 17 n 0 n 
 400
 n n y 5 10 n
 n 0.15 n 0.03 n 0.01 n 0.02
;;; species mass fractions in order o2, co2, co, h2o (and n2 is the rest)
This is for a velocity inlet specified as follows:
Fluent 18.0;
17 m/s specified as normal to the inlet;
with temperature 400K;
turbulence specified as intensity 5 and viscosity ratio 10;
species specified as mass fractions in the order mentioned.
If *any* of those details change *even slightly*, I would need to rejig the TUI command. But, if we're happy with that, here is a command to put into "adjuster-species.scm" (using "string-append" to make it slightly less brain-melting):
Code:
(ti-menu-load-string
  (string-append
    "/define/boundary-conditions/velocity-inlet inlet n n y y n 17 n 0 n "
    (format #f " ~16.8e "
            (pick-a-real "/rep/surf/mwa (outlet) temp n"))
    " n n y 5 10 n "
    (format #f " n ~16.8e "
            (pick-a-real "/rep/surf/mwa (outlet) o2 n"))
    (format #f " n ~16.8e "
            (pick-a-real "/rep/surf/mwa (outlet) co2 n"))
    (format #f " n ~16.8e "
            (pick-a-real "/rep/surf/mwa (outlet) co n"))
    (format #f " n ~16.8e "
            (pick-a-real "/rep/surf/mwa (outlet) h2o n"))))
As a (possibly convenient) side-effect, this command spits a copy of the result to the screen (with "(inlet)" and "#t" as interruptions from Fluent):
Code:
/define/boundary-conditions/velocity-inlet (inlet)
inlet n n y y n 17 n 0 n    3.33000000e+02  n n y 5 10 n  n   0.00000000e+00  n   0.00000000e+00  n   0.00000000e+00  n   0.00000000e+00 #t
Enjoy!

Last edited by obscureed; February 12, 2018 at 15:17. Reason: Minor fix to make inlet speed 17 rather than 16.
obscureed is offline   Reply With Quote

Old   February 26, 2018, 07:51
Default
  #8
New Member
 
Haidor
Join Date: May 2017
Posts: 5
Rep Power: 9
haidory is on a distinguished road
Dear obscureed,

Thank you very much for taking the time to reply to my post. I am frankly not familiar with Scheme programming in Fluent, but I will try to follow you instructions step by step and hopefully I will get it right. Thanks again!!
haidory is offline   Reply With Quote

Old   May 21, 2018, 04:41
Default
  #9
smb
New Member
 
Sergio
Join Date: May 2015
Posts: 10
Rep Power: 11
smb is on a distinguished road
Quote:
Originally Posted by obscureed View Post
Oh, one more thing which might not be easy to pick out of the manual:
to make that UDF work in parallel, you need something like this, after the first face loop and before you calculate "temp":
Code:
#if RP_NODE
  PRF_GRSUM1(area);
  PRF_GRSUM1(sumtemp);
#endif
Dear Obscured,

I used the code wrote by pakk and your tips and I could write the following UDF that does what the OP wanted (I had the same problem).

Howerver, I only can run it in serial mode, If I include your additional lines to parallelize it, I got an error.

Code:
/***********************************************************************
   UDF for specifying steady-state parabolic pressure profile boundary 
   profile for a turbine vane                                          
************************************************************************/

#include "udf.h"

DEFINE_PROFILE(species_profile, t, i)
{
	/* Declare variables */
	face_t f, c;
	Thread *outletthread;
	real A[ND_ND], area=0, sumspecie=0, specie;
	Domain *domain;
	
	domain = Get_Domain(1); /* Returns fluid domain pointer (1 = Mixture) */ 

	outletthread = Lookup_Thread(domain, 12); /* Here put the number of the outlet thread. */

	begin_f_loop(f, outletthread) 
	{ 
		/* Loop through faces of your outlet */
		F_AREA(A, f, outletthread); /* make A the the face vector */
		area += NV_MAG(A);
		sumspecie += F_YI(f, outletthread, i) * NV_MAG(A);
	}
	end_f_loop(f, outletthread);
	
	#if RP_NODE
		PRF_GRSUM1(area);
		PRF_GRSUM1(sumspecie);
	#endif

	specie = sumspecie / area;   /* specie becomes the average specie */

	begin_f_loop(c, t) 
	{
		F_PROFILE(c, t, i) = specie;
	}
	end_f_loop(c, t);
}
Are you sure that those lines are enough to run the UDF in parallel?
smb is offline   Reply With Quote

Old   May 21, 2018, 05:13
Default
  #10
Senior Member
 
Alexander
Join Date: Apr 2013
Posts: 2,363
Rep Power: 34
AlexanderZ will become famous soon enoughAlexanderZ will become famous soon enough
Ansys Fluent Customization manual
Chapter 7. Parallel Considerations

best regards
AlexanderZ is offline   Reply With Quote

Old   May 21, 2018, 06:28
Default
  #11
smb
New Member
 
Sergio
Join Date: May 2015
Posts: 10
Rep Power: 11
smb is on a distinguished road
Quote:
Originally Posted by AlexanderZ View Post
Ansys Fluent Customization manual
Chapter 7. Parallel Considerations

best regards
I've been reading that chapter, but I got an error even when I try to interpret the example of UDF here...

https://www.sharcnet.ca/Software/Flu...df/node218.htm

I got the following error:

mphost_to_node_int_1: no function prototype


Is it possible to interpret these UDF or have to be compiled?
smb is offline   Reply With Quote

Old   May 22, 2018, 09:15
Default
  #12
Senior Member
 
Join Date: Sep 2017
Posts: 246
Rep Power: 12
obscureed is on a distinguished road
Hi smb,


PRF_GRSUM1 is a global reduction macro, which is mentioned in the help files as incompatible with interpreted UDFs. But, to be honest, the number of limitations on an interpreted UDF is so large that I would never even consider using interpreted. Take a deep breath and install a compiler. (There are some useful posts on this -- for example: links to instructions Visual Studio 2017 for udf use - which modules do I need?; troubleshooting errors How to solve UDF compilation problems in Fluent.; the basic steps of compile/load/hook The UDF library you are trying to load (libudf) is not compiled for 3D on the current.)


Good luck!
Ed
obscureed is offline   Reply With Quote

Old   July 4, 2019, 20:02
Question The .c code works for recirculation inlet and outlet?
  #13
Member
 
João Lourenço
Join Date: Jan 2017
Posts: 32
Rep Power: 9
JPBLourenco is on a distinguished road
Dear Sergio and everyone,

I am trying to do a simulation using the re-circulation inlet and outlet boundary condition with multi-species. However, I am having some problems. The overall mass flow rate in the inlet and outlet has the some value (kg/s). But, when I see the amount of mass flow rate in each species, the result is different. If at the outlet of the system extracted 0.08 kg/s of O2, at the inlet of the system we should have the same amount of O2, that is 0.08 kg/s. But this is not happening.

I am using Fluent 16.2 and I would like to know if this problem, when using multi-species, it is corrected in last versions.

The above .c code works? I would like to know just to not lose time if doesn't work.

Thank you for your attention.
JBPLourenco





Quote:
Originally Posted by smb View Post
Dear Obscured,

I used the code wrote by pakk and your tips and I could write the following UDF that does what the OP wanted (I had the same problem).

Howerver, I only can run it in serial mode, If I include your additional lines to parallelize it, I got an error.

Code:
/***********************************************************************
   UDF for specifying steady-state parabolic pressure profile boundary 
   profile for a turbine vane                                          
************************************************************************/

#include "udf.h"

DEFINE_PROFILE(species_profile, t, i)
{
	/* Declare variables */
	face_t f, c;
	Thread *outletthread;
	real A[ND_ND], area=0, sumspecie=0, specie;
	Domain *domain;
	
	domain = Get_Domain(1); /* Returns fluid domain pointer (1 = Mixture) */ 

	outletthread = Lookup_Thread(domain, 12); /* Here put the number of the outlet thread. */

	begin_f_loop(f, outletthread) 
	{ 
		/* Loop through faces of your outlet */
		F_AREA(A, f, outletthread); /* make A the the face vector */
		area += NV_MAG(A);
		sumspecie += F_YI(f, outletthread, i) * NV_MAG(A);
	}
	end_f_loop(f, outletthread);
	
	#if RP_NODE
		PRF_GRSUM1(area);
		PRF_GRSUM1(sumspecie);
	#endif

	specie = sumspecie / area;   /* specie becomes the average specie */

	begin_f_loop(c, t) 
	{
		F_PROFILE(c, t, i) = specie;
	}
	end_f_loop(c, t);
}
Are you sure that those lines are enough to run the UDF in parallel?
JPBLourenco is offline   Reply With Quote

Old   July 5, 2019, 01:08
Default
  #14
Senior Member
 
Join Date: Feb 2010
Posts: 164
Rep Power: 17
gearboy is on a distinguished road
Quote:
Originally Posted by haidory View Post
Hello,

I modeling a room with multiple inlets and outlets. I want one of my inlets to have the same temperature and species concentration as one of my outlets. I tried the recirculation boundary condition in Fluent but it was causing a problem with species convergence. Can I do this using a UDF? Thank you.
Of course you can use UDF to get the averaged temperature and species Yi at the outlet and define them as the inlet bounday.
gearboy is offline   Reply With Quote

Old   July 9, 2019, 05:23
Post
  #15
Member
 
João Lourenço
Join Date: Jan 2017
Posts: 32
Rep Power: 9
JPBLourenco is on a distinguished road
Quote:
Originally Posted by gearboy View Post
Of course you can use UDF to get the averaged temperature and species Yi at the outlet and define them as the inlet bounday.
Dear Gearboy, thank you for your reply.

I am trying to understand how to do a UDF that computes the mass flow rate in each species and how to say that my inlet and outlet have the same value for each one.

Do you know if the code proposed by smb works? How to do it for multi species?

Thank you for your time.
JPBLourenco
JPBLourenco is offline   Reply With Quote

Old   July 10, 2019, 01:01
Default
  #16
Senior Member
 
Alexander
Join Date: Apr 2013
Posts: 2,363
Rep Power: 34
AlexanderZ will become famous soon enoughAlexanderZ will become famous soon enough
ansys fluent customization manual -> DEFINE_PROFILE macro

I recommend you to start with model without species

best regards
AlexanderZ is offline   Reply With Quote

Old   August 31, 2019, 21:21
Default
  #17
New Member
 
Hamza Latif Mehr
Join Date: Jul 2019
Posts: 9
Rep Power: 7
hlmehr is on a distinguished road
Hi,
I've made a code similar to this that will change the inlet temperature with the specific cell ID's temperature. that is
DEFINE_PROFILE(inlettemp,f,c,t,i)
{
real tavg
real temp
face_t f;
real temper=0.0;
real A[ND_ND];
real area= 0.0;
int ID= 78
Thread*t;
d= Get_Domain(1_;
t= Lookup_Thread(d,ID);
tavg=0.0;
begin_f_loop(f,t)
{
F_AREA(A,f,t);
area = NV_MAG(A)*2.0*M_PI;
area_tot +=area;
temper=F_T(f,t);
tavg= temper*area;
}
end_f_loop(f,t)
tavg/= area_tot;
printf("Tavg= %g area_tot = %g\n", tavg, area_tot)
if ((tavg>=305))
{
temp=288;
}
if((tavg<305))
{
temp=305;
}
BEGIN_F_LOOP(c,t)
{
F_PROFILE(c,t)=temp;
}
END_F_LOOP(c,t);
}
But it is not working correctly, i dont know why
hlmehr is offline   Reply With Quote

Old   September 1, 2019, 04:49
Default
  #18
Senior Member
 
Join Date: Nov 2013
Posts: 1,965
Rep Power: 27
pakk will become famous soon enough
Quote:
Originally Posted by hlmehr View Post
...
But it is not working correctly, i dont know why
Please be more specific next time. "not working correctly" can mean so many different things:
  • it didn't comple
  • it crashed Fluent
  • your simulation diverged
  • it gave the wrong answer
  • it sent insulting emails to your mother

Don't make us guess the problem, just tell the problem.

Anyway, you forgot some semicolons at the end of some lines.
pakk is offline   Reply With Quote

Old   September 1, 2019, 05:57
Default
  #19
New Member
 
Hamza Latif Mehr
Join Date: Jul 2019
Posts: 9
Rep Power: 7
hlmehr is on a distinguished road
Dear Pakk,
Apologies for not specifying the problem,
The problems are mainly compilation errors:
1-Semi colons , and i added them with undeclared variables which i did add.
2-it was giving undeclared variable for BEGIN_F_LOOP so i changed it to begin_f_loop and it fixed it.
3-and for line 39 F_PROFILE(c,t) it is giving parse error when i am interpreting it.
The code is as follows:
#include "udf.h"
DEFINE_PROFILE(inlettemp,f,c,t,i)
{
Domain *d;
real area_tot = 0.0;
real tavg;
real temp;
face_t f;
real temper=0;
real A[ND_ND];
real area= 0;
int ID= 1048;
Thread*t;
d= Get_Domain(1);
t= Lookup_Thread(d,ID);
tavg=0.0;
begin_f_loop(f,t)
{
F_AREA(A,f,t);
area = NV_MAG(A)*2.0*M_PI;
area_tot +=area;
temper=F_T(f,t);
tavg= temper*area;
}
end_f_loop(f,t)
tavg/= area_tot;
printf("Tavg= %g area_tot = %g\n", tavg, area_tot);

if ((tavg>=305))
{
temp=288;
}
if((tavg<305))
{
temp=305;
}
begin_f_loop(c,t)
{
F_PROFILE(c,t)=temp;
}
end_f_loop(c,t);
}
Help would be great as my thesis depends on it, thank you
Best regards
hlmehr is offline   Reply With Quote

Reply

Tags
inlet boundary condition, udf code


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
UDF Species source makes my temperature drop... cold fire??? therandomestname Fluent UDF and Scheme Programming 1 November 26, 2015 12:12
Increasing temperature in species transport ssamton FLUENT 2 February 28, 2012 21:37
UDF species equations louiza FLUENT 4 March 10, 2010 02:20
Temperature discontinuity with Species Transport Dominique FLUENT 0 August 31, 2004 21:27
chemical reaction - decompostition La S. Hyuck CFX 1 May 23, 2001 01:07


All times are GMT -4. The time now is 16:20.