Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grackle with COMOVING #349

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open

Grackle with COMOVING #349

wants to merge 11 commits into from

Conversation

YuriOku
Copy link

@YuriOku YuriOku commented Sep 7, 2024

In this PR, I have modified the code to use Grackle with COMOVING. The changes I made are

  • Define Grackle units in Grackle_Init.cpp and Grackle_Prepare.cpp
  • Convert the specific thermal energy between GAMER and Grackle units in Grackle_Prepare.cpp and Grackle_Close.cpp
  • Convert the timestep size to the physical time interval in Grackle_AdvanceDt.cpp
  • Disable normalization of passive scalars for electron and deuterium densities for consistency with Grackle in Init_Field.cpp

I then created a test problem, Grackle_Comoving. The test simulation evolves uniform density gas with an initial temperature of T=1e8 K from z=9 to z=0. The time evolution of density and temperature is recorded in Record__User, and the cooling curve can be computed from the record with the Python script Compute_CoolingCurve.py. There is a C program coolingrate_proper.c, which generates a cooling curve table using Grackle at each redshift, which can be compared with the result of the test simulation.

In the left panel in the figure below, the solid line shows the cooling curve obtained from the test simulation, and the points indicate the values at each redshift. The dotted lines are cooling curves at each redshift. The points lie just on the dotted lines, indicating that the thermal evolution is consistent with the Grackle cooling curve.

CoolingCurve

@hyschive
Copy link
Contributor

hyschive commented Sep 9, 2024

@YuriOku Thanks for the contribution! @ChunYen-Chen will help review your PR.

@ChunYen-Chen
Copy link
Collaborator

Hi @YuriOku, I will review your PR this week and probably finish the review before the weekend.

@ChunYen-Chen
Copy link
Collaborator

Hi @YuriOku, can you share the grackle data CloudyData_noUVB.h5 with me?

@YuriOku
Copy link
Author

YuriOku commented Sep 10, 2024 via email

Copy link
Collaborator

@ChunYen-Chen ChunYen-Chen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @YuriOku,

The PR looks great and I can reproduce your results. I have two questions about your analysis script/tool:

  1. Is there any specific reason you choose -O2 to compile coolingrate_proper.c?
  2. Can you run coolingrate with single precision grackle? If not, there should be some bugs in coolingrate.c.
    • If your tool does not support single precision, please add a check of FLOAT8 in Init_TestProb_Grackle_Comoving.cpp

Before merging, please fix/change the following:

  • Please fix all bugs with comments starting with [BUG].
  • Please update your new code to GAMER code style with the comments starting with [Style]. You can resolve most of the code-style comments by copying the code I wrote in the comment.
  • Please remove all the trailing spaces. You can search them by command:
    grep -r -n "[[:blank:]]$" ./
  • Please provide a simple script for downloading the CloudyData_noUVB.h5, e.g. download_ic.sh in ClusterMerger test problem.

The rest of the comments without tags are some minor change suggestions or requests.

Please let me know if any of my comments is unclear.

example/test_problem/Hydro/Grackle_Comoving/README Outdated Show resolved Hide resolved
src/Grackle/Grackle_AdvanceDt.cpp Outdated Show resolved Hide resolved
src/Grackle/Grackle_Init.cpp Outdated Show resolved Hide resolved
src/Grackle/Grackle_Init.cpp Outdated Show resolved Hide resolved
@YuriOku
Copy link
Author

YuriOku commented Sep 10, 2024

Hi @ChunYen-Chen, thank you for your review! I will address your points.

Is there any specific reason you choose -O2 to compile coolingrate_proper.c?

There is no reason for the option.

Can you run coolingrate with single precision grackle? If not, there should be some bugs in coolingrate.c.
If your tool does not support single precision, please add a check of FLOAT8 in Init_TestProb_Grackle_Comoving.cpp

I have error in running coolingrate with single precision grackle. I will add a check of FLOAT8 in Init_TestProb_Grackle_Comoving.cpp

@ChunYen-Chen
Copy link
Collaborator

Hi @YuriOku,

Is there any specific reason you choose -O2 to compile coolingrate_proper.c?

There is no reason for the option.

How about changing it to -O3?

Can you run coolingrate with single precision grackle? If not, there should be some bugs in coolingrate.c.
If your tool does not support single precision, please add a check of FLOAT8 in Init_TestProb_Grackle_Comoving.cpp

I have error in running coolingrate with single precision grackle. I will add a check of FLOAT8 in Init_TestProb_Grackle_Comoving.cpp

Great, please also update the README in your test problem.

@hyschive
Copy link
Contributor

@YuriOku @ChunYen-Chen

  • It's fine to adopt -O2, which is also the default set-up in GAMER (e.g., configs/spock_intel.config).
  • GAMER prefers single precision for higher GPU performance. So it would be great if both coolingrate_proper.c and Init_TestProb_Grackle_Comoving.cpp could support both single and double precision. Besides, by doing so, we can run GAMER and coolingrate_proper.c using the same floating-point precision so that one only needs to compile Grackle once.
  • Related to the above point, we should validate whether Grackle, GAMER (presumably in Grackle_Init.cpp , and coolingrate_proper.c adopt the same floating-point precision. Does Grackle provide an API to inquire this information?

@YuriOku
Copy link
Author

YuriOku commented Sep 11, 2024

Hi @hyschive,

I see. I will try to run the code with a single precision.

The floating-point precision of Grackle can be checked by sizeof(gr_float).

@hyschive
Copy link
Contributor

So maybe we should re-enable this check. I forget why it was commented out. Please test it.

@YuriOku
Copy link
Author

YuriOku commented Sep 13, 2024

@hyschive @ChunYen-Chen
I have tried to my code in single-float precision, but I could not make it. The Grackle's example C code also fails in single-float precision. I could not identify the cause, but I think this is a bug in Grackle.

Given that Grackle is not recommended run in single-float precision (Grackle Installation Doc), I think it would be better to run Grackle in double precision regardless of the precision of fluid solver. I propose to define h_Che_Array in gr_float, and then, the type conversion is automatically made in Grackle_Prepare and Grackle_Close. An option like GRACKLE_FLOAT can be added to check the precision of Grackle. How do you think?

@hyschive
Copy link
Contributor

@YuriOku

  • I agree with your suggestion and have just filed a feature request Grackle floating-point precision #354.
  • On the other hand, IIUC, @ChunYen-Chen already performed the Grackle_Comoving test in both single and double precision and the results are consistent. So I guess the problem lies in coolingrate_proper.c. @ChunYen-Chen Do you agree?

@hyschive
Copy link
Contributor

@ChunYen-Chen After merging this PR, please help file a follow-up PR to address #354. Thanks.

@YuriOku
Copy link
Author

YuriOku commented Sep 14, 2024

@ChunYen-Chen
I removed the trailing space and added a script to download CloudyData_noUVB.h5. I also updated the code according to your suggestion, leaving two conversations unresolved that I am not sure I have resolved. Could you review them?

After these fixes, I have confirmed that I can reproduce the same results in the test problem Grackle_Comoving.

@ChunYen-Chen
Copy link
Collaborator

@YuriOku Thanks for the update. The PR looks great and I think it is ready to merge.
@hyschive Yes, I do believe the problem is in coolingrate_proper.c.

@hyschive
Copy link
Contributor

@YuriOku Sorry for the delayed progress. We’re planning to merge this PR soon. Could you please update it to resolve the conflicts first?

@YuriOku
Copy link
Author

YuriOku commented Dec 31, 2024

resolved the conflict

Copy link
Contributor

@hsinhaoHHuang hsinhaoHHuang left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @YuriOku,
I have finished the review of this PR.
It is exciting to know GAMER can support Grackle with COMOVING. Thank you for implementing it.

I have raised some questions and added some suggestions in the comments. Could you help me take a look when you have time?
Thanks!

Che_Units.velocity_units = UNIT_V;
Che_Units.a_units = 1.0;
Che_Units.a_value = Time[lv];
# endif

const int Size1pg = CUBE(PS2);
const int Size1v = NPG*Size1pg;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please help align "=" in the next line with Line. 107 and 106.

Comment on lines +121 to +122
// convert from the proper frame to the comoving specific internal energy
Eint = Ptr_sEint[idx_pg] * Dens * SQR(Time[lv]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid confusion, how about "convert from the proper frame specific internal energy to the comoving internal energy density"?

// see https://grackle.readthedocs.io/en/latest/Interaction.html#comoving-coordinates and
// https://github.com/grackle-project/grackle/issues/192
// --> the density and length units are conversion factors from code values to cgs in proper coordinates,
// while the time and velocity units should remain constant, i.e., velocity_units = length_units / (Time * time_units)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although the "Time" here refers to Time in GAMER, which is scale_factor, I think it would cause less confusion if we wrote:
"velocity_units = length_units / (a_value * time_units)".

// https://github.com/grackle-project/grackle/issues/192
// --> the density and length units are conversion factors from code values to cgs in proper coordinates,
// while the time and velocity units should remain constant, i.e., velocity_units = length_units / (Time * time_units)
// --> the specific energy passed to Grackle is u = k_B * T / ((gamma - 1) * mu * m_p)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about adding a reminder here that the specific energy has to be converted to the proper frame as the velocity_units does not change with a?

@@ -58,6 +58,8 @@
# define CONFIG_BFLOAT_4
#endif

#define OMIT_LEGACY_INTERNAL_GRACKLE_FUNC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you provide more information on why this is necessary? I cannot find this in my Grackle.

if ( calculate_cooling_time( &Che_Units, &my_fields, my_cooling_time ) == 0 )
Aux_Error( ERROR_INFO, "Error in calculate_cooling_time.\n" );
// calculate temperature
if ( calculate_temperature(&Che_Units, &my_fields, my_temperature ) == 0 )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ( calculate_temperature(&Che_Units, &my_fields, my_temperature ) == 0 )
if ( calculate_temperature( &Che_Units, &my_fields, my_temperature ) == 0 )

Comment on lines +323 to +329
const double dt_SubStep = Mis_dTime2dt( Time[0], dTime_Base ) * SQR(Time[0]) * UNIT_T;
const double temperature_units = get_temperature_units(&Che_Units); // set temperature units
const double mu = my_temperature[0] / (my_fields.internal_energy[0] * (my_gamma[0] - 1.) * temperature_units);
const double n = Dens / CUBE(Time[0]) * UNIT_D / mu / Const_mp;
const double Edens = Eint * UNIT_P / SQR(Time[0]) / CUBE(Time[0]);
const double Temp = my_temperature[0];
const double Lcool = Edens / fabs(my_cooling_time[0] * UNIT_T) / n / n;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be better to provide some comments to describe these variables.

const double Temp = my_temperature[0];
const double Lcool = Edens / fabs(my_cooling_time[0] * UNIT_T) / n / n;

fprintf( File_User, "%14.7e%14ld%3s%14.7e%14.7e%14.7e%14.7e%14.7e%14.7e", Time[0], Step, "", dt_SubStep, n, mu, Temp, Edens, Lcool );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one thing we should remind the user of is that these values are in the physical frame, which is different from other output data where the values are in the comoving frames when COMOVING is enabled.
Actually, I think it would be better to output the values (e.g., number density, temperature, and internal energy density) both in the comoving and physical frames. It could possibly avoid confusion and also be helpful for analysis.

if ( Aux_CheckFileExist(FileName) ) Aux_Message( stderr, "WARNING : file \"%s\" already exists !!\n", FileName );

FILE *File_User = fopen( FileName, "a" );
fprintf( File_User, "#%13s%14s%3s%14s%14s%14s%14s%14s", "Time", "Step", "", "dt [s]", "n [1/cc]", "mu", "Temp [K]", "Edens [erg/cc], Lcool[erg cm^3 s^-1]" );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is true that Time refers to the scale factor in COMOVING, and it is used in other Record__* files. But with the presence of dt and also all the other variables converted into the physical frame, would you think it is clearer to just use scale factor a for Time in the header?

const double n = Dens / CUBE(Time[0]) * UNIT_D / mu / Const_mp;
const double Edens = Eint * UNIT_P / SQR(Time[0]) / CUBE(Time[0]);
const double Temp = my_temperature[0];
const double Lcool = Edens / fabs(my_cooling_time[0] * UNIT_T) / n / n;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, the cooling rate calculated here is not used to compare the results of the simulation (in Compute_CoolingCurve.py). Instead, we use coolingrate_proper.c to calculate the cooling rate at each redshift to validate the evolution of internal energy in simulations.

It seems that coolingrate_proper.c performs a function similar to the cooling rate calculation here in GAMER, but operates in proper frames and with different temperatures.
Would it be possible to integrate the functionality of coolingrate_proper.c into Aux_Record_GrackleComoving() in GAMER?
We could iterate through various temperatures and get the cooling rate in proper frames as a table of temperatures (possibly output in a separate file) at each step.

This approach would allow us to plot the results after the simulations are complete, eliminating the need to use Grackle for additional calculations.
It would be beneficial if users did not need to compile an additional C program to generate the cooling rate table.
This integration could also prevent potential inconsistencies in parameters used in GAMER and Grackle (e.g., metallicity, primordial_chemistry).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants