Surface output data

Prabin Pradhananga_22497
Prabin Pradhananga_22497 Altair Community Member
edited August 2022 in Community Q&A

Hi experts,

I want to extract integrated surface output data (like total heat flux through the output surface) from a given geometry using udfGetOsiData(). I have attached the geometry, along with the code herewith.

I was able to write to a file, but I could see a large number of data (and lines) even for a single time step. Can anyone tell what's going on here and why I am getting large number of data lines for an integrated result?

Another thing is when I write all time steps, I get tremendous number of lines. Do I need to sum those data lines on my own to get an integrated result?

image

image

image

Best Answer

  • acupro
    acupro
    Altair Employee
    edited August 2022 Answer ✓

    This time also it didn't work.

    I have printed values of firstcall and mytimestep. timestep and mytimestep are both same but also if statement is not working.

    image

    image

     

    In the Stokes intialization portion, firstCall is reported as 1 in the first line - which is correct.  Than everywhere else it is reported as 0 - which is also correct.

    I think mytimestep = timeStep should be inside the if portion after that long line is printed - but maybe that doesn't matter, so long as it gets updated

    But it seems that mytimestep is not being updated to match timeStep

    ******************

    (I'm consulting with a colleague on this...)  Found the issue - mytimestep needs to be a static variable.  Instead of 

    Integer mytimestep ;

    We need

    static Integer mytimestep ;

    This will preserve its memory/value outside of the UDF, rather than getting initialized to 0 each time the UDF is called.

Answers

  • acupro
    acupro
    Altair Employee
    edited August 2022

    You may want to use UDF_OSI_HEAT_FLUX instead of UDF_OSI_CURR_HEAT_FLUX.

    "All quantities are evaluated at the end of the previous time step, except for the "current" variables (UDF_OSI_CURR_MASS_FLUX, UDF_OSI_CURR_MOMENTUM_FLUX, and UDF_OSI_CURR_TRACTION). These are evaluated at the end of every flow stagger in order to provide the latest data."

    You may also want to try writing to the .Log file first, maybe along with some other messages like time step, etc, using udfPrintMess(), to make sure when it's writing the data.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    You may want to use UDF_OSI_HEAT_FLUX instead of UDF_OSI_CURR_HEAT_FLUX.

    "All quantities are evaluated at the end of the previous time step, except for the "current" variables (UDF_OSI_CURR_MASS_FLUX, UDF_OSI_CURR_MOMENTUM_FLUX, and UDF_OSI_CURR_TRACTION). These are evaluated at the end of every flow stagger in order to provide the latest data."

    You may also want to try writing to the .Log file first, maybe along with some other messages like time step, etc, using udfPrintMess(), to make sure when it's writing the data.

    I did as per your instruction--modified the udf and printed data into log file. But I still see many lines of heat_flux. Why am I seeing many lines for an integrated surface output data? Is the UDF being called again and again by acuSolve? I also tried changing from MPI to serial and vice-versa but no improvement.

    image

    image

  • acupro
    acupro
    Altair Employee
    edited August 2022

    I did as per your instruction--modified the udf and printed data into log file. But I still see many lines of heat_flux. Why am I seeing many lines for an integrated surface output data? Is the UDF being called again and again by acuSolve? I also tried changing from MPI to serial and vice-versa but no improvement.

    image

    image

    Yes - it appears the UDF is being called multiple times - thus writing multiple lines of data.

    What does udfPrintMessPrim do (versus udfPrintMess)?

    Did you mean you see the same 'many lines' using a single processor (-np 1) versus using parallel (multiple processors)?

    Can you post the complete .Log file - and the complete loop/portion of the UDF in which you call udfGetOsiData?

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Yes - it appears the UDF is being called multiple times - thus writing multiple lines of data.

    What does udfPrintMessPrim do (versus udfPrintMess)?

    Did you mean you see the same 'many lines' using a single processor (-np 1) versus using parallel (multiple processors)?

    Can you post the complete .Log file - and the complete loop/portion of the UDF in which you call udfGetOsiData?

    I didn't see any differences by changing udfPrintMessPrim versus udfPrintMess.

    Yes, I changed from single processor to multiple and vice versa but no changes--I see multiple number of lines.

    The code is written outside of loop (although there's for loop in my code, but this portion is outside of for loop) but also I see number of lines.

    image

    I have attached log file herewith.

    (I am using a very coarse mesh as a test)

     

    Thanks!

  • acupro
    acupro
    Altair Employee
    edited August 2022

    I didn't see any differences by changing udfPrintMessPrim versus udfPrintMess.

    Yes, I changed from single processor to multiple and vice versa but no changes--I see multiple number of lines.

    The code is written outside of loop (although there's for loop in my code, but this portion is outside of for loop) but also I see number of lines.

    image

    I have attached log file herewith.

    (I am using a very coarse mesh as a test)

     

    Thanks!

    It's going to be difficult to track without the .inp and UDF files. In which command is the UDF being called?  A material model?  A boundary condition?  Can you share the snippet of the .inp that references the UDF?

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    It's going to be difficult to track without the .inp and UDF files. In which command is the UDF being called?  A material model?  A boundary condition?  Can you share the snippet of the .inp that references the UDF?

    Thanks! Here's the input file and C file. I am using momentum_source.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    Thanks! Here's the input file and C file. I am using momentum_source.

    I think I have a better explanation of what's happening.  It's quite likely the UDF is called multiple times during a time step, as blocks/chunks of elements are processed.  What you need to do is check if this is the first time within the time step the UDF is called - and only write the information if it is the first time.  Example:

    Create a variable called MyTimeStep (for example) and set its value to 0

    Before writing the information, compare MyTimeStep to the value from udfGetTimeStep.

    If the values are different:
    Write the information
    Set MyTimeStep to the value from udfGetTimeStep

    This way, the next time the UDF is used, MyTimeStep and the value from udfGetTimeStep are the same, and the information will not get written.

    The next time step, the first time the UDF is called, MyTimeStep and the value from udfGetTimeStep are again different, and the information is written again.  And so on.

    Does that work?

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    I think I have a better explanation of what's happening.  It's quite likely the UDF is called multiple times during a time step, as blocks/chunks of elements are processed.  What you need to do is check if this is the first time within the time step the UDF is called - and only write the information if it is the first time.  Example:

    Create a variable called MyTimeStep (for example) and set its value to 0

    Before writing the information, compare MyTimeStep to the value from udfGetTimeStep.

    If the values are different:
    Write the information
    Set MyTimeStep to the value from udfGetTimeStep

    This way, the next time the UDF is used, MyTimeStep and the value from udfGetTimeStep are the same, and the information will not get written.

    The next time step, the first time the UDF is called, MyTimeStep and the value from udfGetTimeStep are again different, and the information is written again.  And so on.

    Does that work?

    I did as per your instruction. The problem is not solved--I could still see many lines. The thing is each time the UDF is called, MyTimeStep is again assigned value of 0.

    We assign MyTimeStep = udfGetTimeStep at the end of UDF. But, the UDF is closed, UDF is called again by acuSolve and MyTimeStep is again set to 0. Hence, there's no significance of setting MyTimeStep = udfGetTimeStep at the end of UDF.

    image

  • acupro
    acupro
    Altair Employee
    edited August 2022

    I did as per your instruction. The problem is not solved--I could still see many lines. The thing is each time the UDF is called, MyTimeStep is again assigned value of 0.

    We assign MyTimeStep = udfGetTimeStep at the end of UDF. But, the UDF is closed, UDF is called again by acuSolve and MyTimeStep is again set to 0. Hence, there's no significance of setting MyTimeStep = udfGetTimeStep at the end of UDF.

    image

    Right - I was wondering if that might happen.  Let's try this - such that MyTimeStep is set to 0 only if this is the first time the function is called.

    Create a variable called MyTimeStep (for example) and if this is the first time the function is called set its value to 0

    firstCall = udfFirstCall( udfHd ) ;
    if firstCall = 1  >>  set MyTimeStep = 0

    Before writing the information, compare MyTimeStep to the value from udfGetTimeStep.

    If the values are different:
    Write the information
    Set MyTimeStep to the value from udfGetTimeStep

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Right - I was wondering if that might happen.  Let's try this - such that MyTimeStep is set to 0 only if this is the first time the function is called.

    Create a variable called MyTimeStep (for example) and if this is the first time the function is called set its value to 0

    firstCall = udfFirstCall( udfHd ) ;
    if firstCall = 1  >>  set MyTimeStep = 0

    Before writing the information, compare MyTimeStep to the value from udfGetTimeStep.

    If the values are different:
    Write the information
    Set MyTimeStep to the value from udfGetTimeStep

    This time also it didn't work.

    I have printed values of firstcall and mytimestep. timestep and mytimestep are both same but also if statement is not working.

    image

    image

     

  • acupro
    acupro
    Altair Employee
    edited August 2022 Answer ✓

    This time also it didn't work.

    I have printed values of firstcall and mytimestep. timestep and mytimestep are both same but also if statement is not working.

    image

    image

     

    In the Stokes intialization portion, firstCall is reported as 1 in the first line - which is correct.  Than everywhere else it is reported as 0 - which is also correct.

    I think mytimestep = timeStep should be inside the if portion after that long line is printed - but maybe that doesn't matter, so long as it gets updated

    But it seems that mytimestep is not being updated to match timeStep

    ******************

    (I'm consulting with a colleague on this...)  Found the issue - mytimestep needs to be a static variable.  Instead of 

    Integer mytimestep ;

    We need

    static Integer mytimestep ;

    This will preserve its memory/value outside of the UDF, rather than getting initialized to 0 each time the UDF is called.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    In the Stokes intialization portion, firstCall is reported as 1 in the first line - which is correct.  Than everywhere else it is reported as 0 - which is also correct.

    I think mytimestep = timeStep should be inside the if portion after that long line is printed - but maybe that doesn't matter, so long as it gets updated

    But it seems that mytimestep is not being updated to match timeStep

    ******************

    (I'm consulting with a colleague on this...)  Found the issue - mytimestep needs to be a static variable.  Instead of 

    Integer mytimestep ;

    We need

    static Integer mytimestep ;

    This will preserve its memory/value outside of the UDF, rather than getting initialized to 0 each time the UDF is called.

    This time also it didnt work. I think when UDF is called back again by acuSolve, mytimestep is set back to 0.

    image 

  • acupro
    acupro
    Altair Employee
    edited August 2022

    This time also it didnt work. I think when UDF is called back again by acuSolve, mytimestep is set back to 0.

    image 

    I edited that last comment a few time - maybe you missed this part:

    For defining the variable mytimestep - before it's initializes/used - instead of

    Integer mytimestep ;

    We need

    static Integer mytimestep ;

    This will preserve its memory/value outside of the UDF, rather than getting initialized to 0 each time the UDF is called.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    I edited that last comment a few time - maybe you missed this part:

    For defining the variable mytimestep - before it's initializes/used - instead of

    Integer mytimestep ;

    We need

    static Integer mytimestep ;

    This will preserve its memory/value outside of the UDF, rather than getting initialized to 0 each time the UDF is called.

    Thank you very much for your effort--I really appreciate it. It worked this time.

    image

     

  • acupro
    acupro
    Altair Employee
    edited August 2022

    Thank you very much for your effort--I really appreciate it. It worked this time.

    image

     

    Excellent!  We both learned something from this question.

    Hopefully it still works writing to your external file.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Hi experts,

    I have another question regarding the same.

    I used the log file in HWCFD to create table from convert tool>>>surface output>>>heat_flux. I see that the values are not zero in osi. But, using udfGetOsiData() is giving every value equal to zero. What could be the reason?

    image

     

  • acupro
    acupro
    Altair Employee
    edited August 2022

    Hi experts,

    I have another question regarding the same.

    I used the log file in HWCFD to create table from convert tool>>>surface output>>>heat_flux. I see that the values are not zero in osi. But, using udfGetOsiData() is giving every value equal to zero. What could be the reason?

    image

     

    Does it make a difference if you format the output of heat_flux as 16.12f instead of 0.12f?

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Does it make a difference if you format the output of heat_flux as 16.12f instead of 0.12f?

    No, it didn't make any changes in the value. Only spacing is changed. Same output as before.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    No, it didn't make any changes in the value. Only spacing is changed. Same output as before.

    Also - if this is an outlet, you really should be using UDF_OSI_CONVECTIVE_TEMPERATURE instead of UDF_OSI_HEAT_FLUX.  This would correspond to convective_temperature_flux in the Convert tool. The OSI Heat Flux should be very close to zero at inlet or outlet.

    If you use those variables instead - are they consistent?

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Also - if this is an outlet, you really should be using UDF_OSI_CONVECTIVE_TEMPERATURE instead of UDF_OSI_HEAT_FLUX.  This would correspond to convective_temperature_flux in the Convert tool. The OSI Heat Flux should be very close to zero at inlet or outlet.

    If you use those variables instead - are they consistent?

    No, all values are still zero when I changed to UDF_OSI_CONVECTIVE_TEMPERATURE.

    I tried as a test by changing to UDF_OSI_TEMPERATURE, UDF_OSI_MASS_FLUX, etc. and everything is zero.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    No, all values are still zero when I changed to UDF_OSI_CONVECTIVE_TEMPERATURE.

    I tried as a test by changing to UDF_OSI_TEMPERATURE, UDF_OSI_MASS_FLUX, etc. and everything is zero.

    I built a simple test case, and see the same behavior.  I've submitted my test case to development so they can check what's happening.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    I built a simple test case, and see the same behavior.  I've submitted my test case to development so they can check what's happening.

    Thanks. I look for an update soon.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    Thanks. I look for an update soon.

    Actually this was our mistake in the C code.  The heat-flux, convective-temperature-flux, etc OSI data are stored in arrays - so we need to reference the proper location in the array(s) to get the value.

    Example:
    udfPrintMessPrim( udfHd, "Heat Flux at %d = %0.12f\n", timeStep, heat_flux[0] ) ;

    I've added [0] to the heat_flux name - we need the zeroth (or first) entry of that array.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    Again - at inlet/outlet, it's better to use convective temperature flux, as heat flux should be approximately zero, as there should be close to zero temperature difference across the inlet/outlet.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Actually this was our mistake in the C code.  The heat-flux, convective-temperature-flux, etc OSI data are stored in arrays - so we need to reference the proper location in the array(s) to get the value.

    Example:
    udfPrintMessPrim( udfHd, "Heat Flux at %d = %0.12f\n", timeStep, heat_flux[0] ) ;

    I've added [0] to the heat_flux name - we need the zeroth (or first) entry of that array.

    I have more question: When I declare heat_flux, should I declare it as array or as real? 

    Real* heat_flux OR Real* heat_flux[size]

    If it it an array then, should I use the latter? But the latter didn't work.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    I have more question: When I declare heat_flux, should I declare it as array or as real? 

    Real* heat_flux OR Real* heat_flux[size]

    If it it an array then, should I use the latter? But the latter didn't work.

    Real* heat_flux is correct

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Real* heat_flux is correct

    Thanks! It is working now. But, I am missing the data for last time step.

  • acupro
    acupro
    Altair Employee
    edited August 2022

    Thanks! It is working now. But, I am missing the data for last time step.

    Correct - the UDF is writing the values at the start of the time step the first time the UDF is called - which would give values consistent with the end of the previous time step.

  • Prabin Pradhananga_22497
    Prabin Pradhananga_22497 Altair Community Member
    edited August 2022

    Correct - the UDF is writing the values at the start of the time step the first time the UDF is called - which would give values consistent with the end of the previous time step.

    Thank you for your effort!