Ansys Learning Forum Maintenance

NOTICE: We will be performing backend maintenance of our Learning Forum from April 5 to April 12, 2021. The result will be a new infrastructure but with little impact to user experience and design. Currently the forum is accessible in read-only mode as we complete our final migration. Thank you for your patience. For urgent issues please visit HERE.


Undulation motion of Fish using UDF — Ansys Learning Forum

Undulation motion of Fish using UDF

MohamedAyman1MohamedAyman1 Member Posts: 10

Hello!!

I hope this message finds you all well. I am working on a 2D case of airfoil shape (NACA0012) and trying to make the undulation motion of the fish using GRID_MOTION macro. I have created the UDF and compile it successfully however, Instead of moving the Walls of the airfoil, the centerline is moving with the expected motion. I have attached two photos; one for the airfoil and the other is for the Centerline movement. How can I solve this problem to give the motion to the airfoil wall not the centerline?.

Thanks in advance🙂


Comments

  • YasserSelimaYasserSelima Member Posts: 929

    Why are you using GRID_MOTION? grid_motion is mainly designed if the shape of the body changes ... inflation, shrinkage, bending .. etc. If the shape of the airfoil remains constant, and it only rotates, and translates .. you don't need to Use Grid_motion.


    I recommend using DEFINE_CG_MOTION ... this would shorten your code.

  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    Thanks for replying. Actually the airfoil body is changing and cannot be treated as a rigid body that only rotates and translates which is knowing as flapping motion (pitching + plunging). DEFINE_CG_MOTION is the perfect choice for that case as you said but, in my case, the airfoil shape is changing with time to generate the undulation motion a s illustrated in figure 2. My problem is that the centerline is moving with the motion instead of the airfoil's wall.

  • YasserSelimaYasserSelima Member Posts: 929

    In this case, you are right ...GRID_MOTION is the right choice.

    So, why is the centerline defined in Fluent? Are you defining the airfoil body as a solid zone?

  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    The centerline is not defined in FLUENT and the airfoil's wall is defined in named selection. I really don't know why the airfoil itself does NOT undulate. The airfoil is subtracted from the fluid domain so it is all fluid. ANY HELP?!!

  • YasserSelimaYasserSelima Member Posts: 929

    I am not sure why is this happening .. seems weird ... one more question, how did you recognise that the centerline is moving?


    For debugging,I would suggest you simplify the motion and see if the problem still occur. Like give it a translation motion ... Also you can print the NODE_Y before and after the update and see if the values change like what you want or not.

    I might be able to help you debugging if you don't mind posting the UDF

  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    Thanks for offering help. Actually, I tried the rotating motion of the airfoil (Pitching mechanism) by  DEFINE_CG_MOTION and the motion was as expected but when I try the undulation motion by DEFINE GRID_MOTION the airfoil two lines merges to one line which seems to be the centerline. I didn't understand what do you mean f print NODE_Y before the update. Below is the UDF:

    #include "udf.h"

    #include "dynamesh_tools.h"

    #include "math.h"

    #define U 40.05

    #define L 1.00

    #define a0 0.02

    #define a1 0.08

    #define a2 0.16


    DEFINE_GRID_MOTION(Fish_movment, domain, dt, time, dtime)

    {

    Thread *tf = DT_THREAD(dt); /* pointer to a thread*/

    face_t f;

    int n;

    Node *node_p;

    real A, x, y, wave, sign;

    real St = 0.05;

    /* set deforming flags */

    SET_DEFORMING_THREAD_FLAG(THREAD_T0(tf));  /* means that the nodes adjacent to the moving wall will be defrormed to avoid skewness*/

    begin_f_loop(f, tf)

    {

    f_node_loop(f, tf, n)

    {

    node_p = F_NODE(f, tf, n);

    /* Update the current node only is not been visited before*/


    if (NODE_POS_NEED_UPDATE(node_p))

    {

    /*Set flag to indicate that the node position has been updated*/

    NODE_POS_UPDATED(node_p);

    x = NODE_X(node_p);

    A = a0 - a1*x + a2*x*x;

    wave = 2 * M_PI / L;

    sign = x - St * U * time;

    y = A * sin(wave*sign);

    NODE_Y(node_p) = y;

    }

    }

    }

    end_f_loop(f, tf);

    }


    I really appreciate your help.😀

  • YasserSelimaYasserSelima Member Posts: 929


    Try this and see if you have a difference or not. Change the NODE_Y(node_p) = y; to

    NODE_Y(node_p) += y;
    


    Let me know

  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    Really thanks for your help. The code works and the airfoil's wall is moving instead of only one line. But, there is something strange happening, the airfoil is stretched in a strange shape as illustrated in Figure 1. But when I use a time step of 0.05 (For viewing the motion only) the motion looks good as illustrated in figure 2. When coming to setup and solving, I expect to decrease the time step for solver stability and validation of the results also. To conclude what I said:

    1) The motion below 0.05 is not correct and the airfoil is stretched.

    2) The motion is occurring on one side only.

    3) Is there is something wrong with the UDF?

    Again thank you for your help.😀




  • YasserSelimaYasserSelima Member Posts: 929

    Hello,

    You are welcome.

    1) I am not sure why is this happening. The amplitude is not function of time. So this is really odd. Can you review all the equations , specially the amplitude A ... and try view motion with small time step and see if same thing is repeated or not

    2) The second image you posted shows clearly that motion is happening on the two sides. Start from loading the original geometry ...

    add this below Node_y(node_p) line

    #if RP_HOST
    Message(" x = %f , y = %f \n", x, y);
    #endif
    

    Run two time steps only ... this should print the values of x and y of all nodes and see if they are updated right or not. Depending on your mesh size, expect to have many lines printed ... so, run it for two time steps only.


    3) I don't think there is something wrong

  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    Sorry or the late reply. Again, I really appreciate your effort in helping me. Here are what I done:

    1) I checked the amplitude equation again and there is nothing wrong in the equation.

    2) I tried to change the strouhal number to see if the stretching foil is occurring or not but the same thing happened.

    3) The lower the time step, the more the stretching of the foil.

    4) The motion is occurring on only one side and then moves to equilibrium position and moves to the same side not the other one.

    5) I didn't understand the benefit of:

    #if RP_HOST
    Message(" x = %f , y = %f \n", x, y);
    #endif
    

    6) Is it possible to share the Case file with you to understand what I mean?. Just sent me your mail.

    Again thank you for you help😀

  • YasserSelimaYasserSelima Member Posts: 929

    Hello,

    No need for sending the case. I think I did understood the issue. Here is my suggested solution .. This solution uses y_centerline as the position of the centerline.. I am assuming you know it as a function of x

    • Increase the number of User Defined Node Memory locations to 1 before compiling the code.
    • Before starting the simulation you need to save in the N_UDMI how far are they from the centerline ... Could be done by DEFINE_EXCUTE_ON_DEMAND
    • In your GRID_MOTION function, you will have NODE_Y(node_p) = y + N_UDMI(f,tf,0);


    Here is an example of the define_on_demand

     
    DEFINE_EXECUTE_ON_DEMAND(init_value)
    {
       
       Domain *d; 
       Thread *tf;
       face_t f;
       Node *node_p;
       int n;
       real x, y_centerline;
       begin_f_loop(f, tf)
       d = Get_Domain(1);     
       tf = Lookup_Thread(d,zone_ID);
       {
           f_node_loop(f, tf, n)
           {
               node_p = F_NODE(f, tf, n);
    	   x = NODE_X(node_p);
               y_centerline = ... ;               /* calculate centerline position as f(x) */ 
               N_UDMI(node_p, 0) = NODE_Y(node_p) - y_centerline; 
          }
      }
    }
    


    In the above, you need to add

    • zone_ID you can get this from the boundary conditions ...
    • y_centerline equation in terms of x .. if it is constant, just put the value.


    And definitely check syntax errors and typos ...


    Let me know if it works. Good Luck!

  • YasserSelimaYasserSelima Member Posts: 929

    Don't forget to run the function before the simulation

  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    I hope this message finds you well. Actually the DEFINE_EXCUTE _ON_DEMAND macro cannot be interpreted nor compiled successfully. I followed your instructions well and

    put the zone ID and the equation of the airfoil itself to define the distance from the centerline which is attached in the next figure to check it:

    But the DEFINE_EXCUTE _ON_DEMAND cannot be into the solver successfully. I checked the syntax and added #include "udf.h" and #include "math.h" before your code and still no results. I removed the "EXCUTE" word as said in the UDF manual but no result. Cannot know the exact problem!!!!!. Any ideas?

    Again, thanks for your help.

    Mohamed

  • YasserSelimaYasserSelima Member Posts: 929

    DEFINE_ON_DEMAND

  • YasserSelimaYasserSelima Member Posts: 929
    edited April 5

    what is the error message?

    try it like this


    #include "udf.h"
    
    DEFINE_ON_DEMAND(init_value)
    {
       
       Domain *d; 
       Thread *tf;
       face_t f;
       Node *node_p;
       int n;
       real x, y_centerline;
       d = Get_Domain(1);     
       tf = Lookup_Thread(d,zone_ID);
    
    
    
       begin_f_loop(f, tf)
          {
           f_node_loop(f, tf, n)
           {
               node_p = F_NODE(f, tf, n);
    	   x = NODE_X(node_p);
               y_centerline = ... ;               /* calculate centerline position as f(x) */ 
               N_UDMI(node_p, 0) = NODE_Y(node_p) - y_centerline; 
          }
      }
    }
    


  • MohamedAyman1MohamedAyman1 Member Posts: 10

    Dear Yasser,

    Thanks for the fast reply. The UDF cannot be compiled nor interpreted successfully. Attached is the UDF for you to check it:

    #include "udf.h"


    DEFINE_ON_DEMAND(init_value)

    {

      

      Domain *d; 

      Thread *tf;

      face_t f;

      Node *node_p;

      int n;

      real x, y_centerline;

      d = Get_Domain(1);   

      tf = Lookup_Thread(d,2);



      begin_f_loop(f, tf)

       {

        f_node_loop(f, tf, n)

        {

          node_p = F_NODE(f, tf, n);

      x = NODE_X(node_p); 

          y_centerline = 0.6*(0.2969*sqrt(x)-0.1260*x-0.3516*(pow(x,2))+0.2843*(pow(x,3))-0.1015*(pow(x,4))) ;        

          N_UDMI(node_p, 0) = NODE_Y(node_p) - y_centerline ; 

       }

     }

    }


    the error message is attached in the next figure when I interpret the UDF:

    I cannot understand the error exactly.

    Thanks,

    Mohamed

  • YasserSelimaYasserSelima Member Posts: 929

    @MohamedAyman1

    it was missing end_f_loop


    now it compiles on my computer


    DEFINE_ON_DEMAND(init_value)
    {
     Domain *d; 
     Thread *tf;
     face_t f;
     Node *node_p;
     int n;
     real x, y_centerline;
     d = Get_Domain(1);  
     tf = Lookup_Thread(d,2);
    
     begin_f_loop(f, tf)
      {
      f_node_loop(f, tf, n)
      {
       node_p = F_NODE(f, tf, n);
       x = NODE_X(node_p); 
       y_centerline = 0.6*(0.2969*sqrt(x)-0.1260*x-0.3516*(pow(x,2))+0.2843*(pow(x,3))-0.1015*(pow(x,4))) ;     
       N_UDMI(node_p, 0) = NODE_Y(node_p) - y_centerline ; 
      }
     }
     end_f_loop(f, tf)
    } 
    


Sign In or Register to comment.