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

Bang-bang control in Fluent

Register Blogs Community New Posts Updated Threads Search

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   October 19, 2022, 23:20
Question Bang-bang control in Fluent
  #1
New Member
 
Jared
Join Date: Oct 2022
Posts: 4
Rep Power: 3
jpaora is on a distinguished road
Hi all,


I am looking to implement a bang-bang control system so that when a component exceeds an allowable temperature (T_max), it is shut off, until the temperature returns below a second value (T_min), then it is turned on again.


In other words,
If T > Tmax, P = 0
If Tmax < T < Tmin, P = P (at previous time step)

If T < Tmin, P = 4000 W/m^3


I have linked the source term in a cell zone to an expression - but the expression is undefined as it contains a circular reference. Is there a different way to do this, as it seems like a fairly innocuous request. Here's what I have so far anyway:

Expression is called "cam_power".
IF(Tc>Tmax, 0 [W*m^-3], IF(AND(Tc<Tmax,Tc>Tmin),cam_power,4000 [W*m^-3]))


Appreciate any help I can receive!
jpaora is offline   Reply With Quote

Old   October 20, 2022, 00:17
Default
  #2
Senior Member
 
Alexander
Join Date: Apr 2013
Posts: 2,363
Rep Power: 34
AlexanderZ will become famous soon enoughAlexanderZ will become famous soon enough
you may use UDF
look for define_profile macro
__________________
best regards


******************************
press LIKE if this message was helpful
AlexanderZ is offline   Reply With Quote

Old   October 20, 2022, 04:28
Default
  #3
New Member
 
Join Date: Sep 2021
Posts: 7
Rep Power: 4
North Star is on a distinguished road
Hi,

I was able to do a similar simulation with just using expressions in 2020R1.

Creating two points (my temp sensor locations) as report definitions and attaching them to a constant flux boundary as a piecewise eqn. (just like you did) worked just fine for me.

However I only had two flux options, say 0 and 4000 as in your case.

IF(Tc>Tmax, 0 [W*m^-3], IF(Tc<Tmin),4000 [W*m^-3]) would be how I approach it.

By this way if your sensor temperature (Tc) exceeds your cutoff temperature (Tmax), flux is set to zero until the sensor sees Tmin. Other way around if it drops below Tmin, 4000 is applied until it goes above Tmax again. This way you can keep your system between Tmax and Tmin (you will have to account for peak overshoot).

Try plotting the flux at your boundary with this method. You should be able to see a square signal.
North Star is offline   Reply With Quote

Old   October 20, 2022, 16:13
Default
  #4
New Member
 
Jared
Join Date: Oct 2022
Posts: 4
Rep Power: 3
jpaora is on a distinguished road
Thanks for the reply.
The issue I am facing with this suggestion is I must provide a false value for the second IF statement so that if it is in the range Tmin < Tc < Tmax it must have a value. As far as I know I can't access the data at the previous timestep to continue what it was doing before - or checking the temporal temperature gradient to see if it is cooling or heating
jpaora is offline   Reply With Quote

Old   October 20, 2022, 21:48
Default
  #5
New Member
 
Jared
Join Date: Oct 2022
Posts: 4
Rep Power: 3
jpaora is on a distinguished road
Quote:
Originally Posted by AlexanderZ View Post
you may use UDF
look for define_profile macro

Thanks, I was reluctant to learn UDF's but I guess it is unavoidable now.


As far as I can tell, it seems I need to use the DEFINE_SOURCE macro for heat generation. I found the following from an old post which was very helpful but I am unsure how to progress it further how to write udf for a component source term on a wall ?



Code:
#include "udf.h"

DEFINE_ON_DEMAND(selecting_the_cells)
{
    #if !RP_HOST
        Domain *d;
        Thread *t, *tc, *t0;
        face_t f;
        cell_t c, c0;
        d=Get_Domain(1);
        tc=Lookup_Thread(d,9); //thread pointer of the surface (the ID can be obtained from the boundary condition panel)
        //Loop through all the cell threads in the domain
        thread_loop_c(t,d)
        {
            //Loop through the cells in each cell thread
            begin_c_loop(c,t)
            {
                C_UDMI(c,t,0)=0;    
            }
            end_c_loop(c,t)
        }
        
        begin_f_loop(f,tc)
        {
            c0=F_C0(f,tc);
            t0=THREAD_T0(tc);
            C_UDMI(c0,t0,0)=1;
        }
        end_f_loop(f,tc)
    #endif
}

DEFINE_SOURCE(energy_source, c, t, dS, eqn)
{
    real source;
    if (C_UDMI(c,t,0)>0.)
    {
        source=1000.;
        dS[eqn]=0.;
    }
    else
    {
        source=0.;
        dS[eqn]=0.;
    }
    return source;
}
My problem is I want to measure the max temperature in a solid after each time step and I am not sure how to do this using the DEFINE_ON_DEMAND macro. I can tell I need to use a data access macro like C_T(c,t) to obtain the temperature but I don't understand how to find the max temperature in this cell zone. I can do the conditional logic but my understanding falls short for accessing the solution data
jpaora is offline   Reply With Quote

Old   October 21, 2022, 00:42
Default
  #6
Senior Member
 
Alexander
Join Date: Apr 2013
Posts: 2,363
Rep Power: 34
AlexanderZ will become famous soon enoughAlexanderZ will become famous soon enough
your exact request is unclear, as code above is doing other things, comparing to your first message.

code below is:
- getting min, max and average temperatures of solid zone (in code it has ID = 9, in your model could be different)
- defining source value depending on tmax
- applying source

Code:
#include "udf.h"

real source = 0.0;

DEFINE_EXECUTE_AT_END(calculate_source)
{
	Domain *d;
	real tavg = 0.;
	real tmax = 0.;
	real tmin = 0.;
	real temp,volume,vol_tot;
	Thread *t;
	cell_t c;
	d = Get_Domain(1);
	/* Loop over all cell threads in the domain */
	t=Lookup_Thread(d,9); /* thread pointer of the solid zone (the ID can be obtained from the boundary condition panel)*/

	begin_c_loop(c,t)
	{
		volume = C_VOLUME(c,t); /* get cell volume */
		temp = C_T(c,t); /* get cell temperature */
		if (temp < tmin || tmin == 0.) tmin = temp;
		if (temp > tmax || tmax == 0.) tmax = temp;
		vol_tot += volume;
		tavg += temp*volume;
	}
	end_c_loop(c,t)
	tavg /= vol_tot;
	Message0("\n Tmin = %g Tmax = %g Tavg = %g\n",tmin,tmax,tavg);
	
	if (tmax > 500) source = 1000.0;
	else  source = 0.0;
}

DEFINE_SOURCE(energy_source, c, t, dS, eqn)
{
    return source;
}
__________________
best regards


******************************
press LIKE if this message was helpful
AlexanderZ is offline   Reply With Quote

Old   October 25, 2022, 19:05
Default
  #7
New Member
 
Jared
Join Date: Oct 2022
Posts: 4
Rep Power: 3
jpaora is on a distinguished road
Quote:
Originally Posted by AlexanderZ View Post
your exact request is unclear, as code above is doing other things, comparing to your first message.

code below is:
- getting min, max and average temperatures of solid zone (in code it has ID = 9, in your model could be different)
- defining source value depending on tmax
- applying source

Code:
#include "udf.h"

real source = 0.0;

DEFINE_EXECUTE_AT_END(calculate_source)
{
    Domain *d;
    real tavg = 0.;
    real tmax = 0.;
    real tmin = 0.;
    real temp,volume,vol_tot;
    Thread *t;
    cell_t c;
    d = Get_Domain(1);
    /* Loop over all cell threads in the domain */
    t=Lookup_Thread(d,9); /* thread pointer of the solid zone (the ID can be obtained from the boundary condition panel)*/

    begin_c_loop(c,t)
    {
        volume = C_VOLUME(c,t); /* get cell volume */
        temp = C_T(c,t); /* get cell temperature */
        if (temp < tmin || tmin == 0.) tmin = temp;
        if (temp > tmax || tmax == 0.) tmax = temp;
        vol_tot += volume;
        tavg += temp*volume;
    }
    end_c_loop(c,t)
    tavg /= vol_tot;
    Message0("\n Tmin = %g Tmax = %g Tavg = %g\n",tmin,tmax,tavg);
    
    if (tmax > 500) source = 1000.0;
    else  source = 0.0;
}

DEFINE_SOURCE(energy_source, c, t, dS, eqn)
{
    return source;
}

Great! That helped a lot.
Here is my working code (some of it is a bit ugly and redundant as I didn't want to waste simulation time, but it works )


Code:
#include "udf.h"

real source_p1 = 0;
real source_p2 = 0;
real source_p3 = 0;
int state = 1; /*  1 is ON, 0 is OFF */

DEFINE_EXECUTE_AT_END(calculate_source)
{
    real tmax = 0.;
    real tmin = 0.;
    real thigh = 315; /* allowable max */
    real tlow = 310; /* allowable min */
    real temp;

    /* ====== p1 ====== */
    Domain *d;
    Thread *t;
    cell_t c;
    d = Get_Domain(1);
    t=Lookup_Thread(d,106); /* thread pointer of the solid zone (the ID can be obtained from the boundary condition panel)*/

    /* ====== p2 ====== */
    Domain *dp;
    Thread *tp;
    cell_t cp;
    dp = Get_Domain(1);
    tp=Lookup_Thread(dp,96); /* thread pointer of the solid zone (the ID can be obtained from the boundary condition panel)*/

    /* ====== p3 ====== */
    Domain *di;
    Thread *ti;
    cell_t ci;
    di = Get_Domain(1);
    ti=Lookup_Thread(di,1048); /* thread pointer of the solid zone (the ID can be obtained from the boundary condition panel)*/

    begin_c_loop(c,t)     /* Loop over all cell threads in the p1 domain */
    {
        temp = C_T(c,t); /* get cell temperature using C_T*/
        if (temp < tmin || tmin == 0.) tmin = temp; /* find min temp */
        if (temp > tmax || tmax == 0.) tmax = temp; /* find max temp */
    }
    end_c_loop(c,t)

    begin_c_loop(cp,tp)     /* Loop over all cell threads in the p2 domain */
    {
        temp = C_T(cp,tp); /* get cell temperature using C_T*/
        if (temp < tmin || tmin == 0.) tmin = temp; /* find min temp */
        if (temp > tmax || tmax == 0.) tmax = temp; /* find max temp */
    }
    end_c_loop(cp,tp)
    
    begin_c_loop(ci,ti)     /* Loop over all cell threads in the p3 domain */
    {
        temp = C_T(ci,ti); /* get cell temperature using C_T*/
        if (temp < tmin || tmin == 0.) tmin = temp; /* find min temp */
        if (temp > tmax || tmax == 0.) tmax = temp; /* find max temp */
    }
    end_c_loop(ci,ti)

    Message("\n Tmin = %g Tmax = %g\n",tmin,tmax);
    Message("\n Controller = %g\n",state);

    if (tmax > thigh) state = 0; /* turn off */
    if (tmin < tlow) state = 1; /* turn on */
}

DEFINE_SOURCE(p1_source, c, t, dS, eqn)
{
    if (state == 1) source_p1 = 42900;
    else source_p1 = 0;
    return source_p1;
}

DEFINE_SOURCE(p2_source, cp, tp, dS, eqn)
{
    if (state == 1) source_p2 = 25800;
    else source_p2 = 0;
    return source_p2;
}

DEFINE_SOURCE(p3_source, ci, ti, dS, eqn)
{
    if (state == 1) source_p3 = 12200;
    else source_p3 = 0;
    return source_p3;
}

DEFINE_REPORT_DEFINITION_FN(control_state)
{
    return state;
}
jpaora is offline   Reply With Quote

Reply

Tags
conditional, expressions


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
Fluent exit frequently with error ‘Unable to parse’ running on remote clusters Gang Shen Fluent Multiphase 5 February 7, 2022 03:02
Building problems with cell zones when reopening Fluent MJ2017 FLUENT 0 October 14, 2017 08:11
Error in reading Fluent 13 case file in fluent 12 apurv FLUENT 2 July 12, 2013 07:46
Problems in lauching FLUENT Lourival FLUENT 3 January 16, 2008 16:48
fluent transient simulation control Kai Kang FLUENT 0 January 20, 2000 12:52


All times are GMT -4. The time now is 12:07.