diff --git a/doc/wiki/Runtime-Parameters-related/Runtime-Parameters:-Outputs.md b/doc/wiki/Runtime-Parameters-related/Runtime-Parameters:-Outputs.md index 71dbedb1c..b90cf491a 100644 --- a/doc/wiki/Runtime-Parameters-related/Runtime-Parameters:-Outputs.md +++ b/doc/wiki/Runtime-Parameters-related/Runtime-Parameters:-Outputs.md @@ -5,6 +5,7 @@ Parameters described on this page: [OPT__OUTPUT_TEXT_LENGTH_INT](#OPT__OUTPUT_TEXT_LENGTH_INT),   [OPT__OUTPUT_USER](#OPT__OUTPUT_USER),   [OPT__OUTPUT_PAR_MODE](#OPT__OUTPUT_PAR_MODE),   +[OPT__OUTPUT_PAR_ADDI_ATTR](#OPT__OUTPUT_PAR_ADDI_ATTR),   [OPT__OUTPUT_PAR_MESH](#OPT__OUTPUT_PAR_MESH),   [OPT__OUTPUT_BASEPS](#OPT__OUTPUT_BASEPS),   [OPT__OUTPUT_BASE](#OPT__OUTPUT_BASE),   @@ -100,6 +101,13 @@ This option is mainly for debugging purposes since the simulation snapshots particle data. * **Restriction:** + +* #### `OPT__OUTPUT_PAR_ADDI_ATTR`   (0=off, 1=time, 2=acc, 3=acc+time)   [0] + * **Description** +Output particle addition data (time or acceleration) to snapshots (`Data_******`) file. + * **Restriction:** +Only applicable when enabling [[--particle | Installation:-Option-List#--particle]] and [[--store_par_acc | Installation:-Option-List#--store_par_acc]] + * #### `OPT__OUTPUT_PAR_MESH`   (0=off, 1=on)   [1] * **Description:** diff --git a/example/test_problem/Template/Input__Parameter b/example/test_problem/Template/Input__Parameter index d7742ab30..104b33448 100644 --- a/example/test_problem/Template/Input__Parameter +++ b/example/test_problem/Template/Input__Parameter @@ -384,6 +384,8 @@ OPT__OUTPUT_TEXT_FORMAT_FLT %24.16e # string format of floating-point vari OPT__OUTPUT_TEXT_LENGTH_INT 12 # string length of integer variables in output text files [12] OPT__OUTPUT_USER 0 # output the user-specified data -> edit "Output_User.cpp" [0] OPT__OUTPUT_PAR_MODE 0 # output the particle data: (0=off, 1=text-file, 2=C-binary) [0] ##PARTICLE ONLY## +OPT__OUTPUT_PAR_ADDI_ATTR 0 # output particle additional attributes(time, acceleration...etc) to snapshots. ##STORE_PAR_ACC ONLY## + # (0=off, 1=time, 2=acc, 3=time+acc) [0] OPT__OUTPUT_PAR_MESH 1 # output the attributes of tracer particles mapped from mesh quantities -> edit "Input__Par_Mesh" [1] ##PARTICLE ONLY## OPT__OUTPUT_BASEPS 0 # output the base-level power spectrum [0] OPT__OUTPUT_BASE 0 # only output the base-level data [0] ##OPT__OUTPUT_PART ONLY## diff --git a/include/Global.h b/include/Global.h index aabea2f5b..341ff0394 100644 --- a/include/Global.h +++ b/include/Global.h @@ -241,7 +241,7 @@ extern bool FFTW3_Double_OMP_Enabled, FFTW3_Single_OMP_Enabled; #ifdef PARTICLE extern double DT__PARVEL, DT__PARVEL_MAX, DT__PARACC; extern bool OPT__CK_PARTICLE, OPT__FLAG_NPAR_CELL, OPT__FLAG_PAR_MASS_CELL, OPT__FREEZE_PAR, OPT__OUTPUT_PAR_MESH, OPT__PAR_INIT_CHECK; -extern int OPT__OUTPUT_PAR_MODE, OPT__PARTICLE_COUNT, OPT__FLAG_NPAR_PATCH, FlagTable_NParPatch[NLEVEL-1], FlagTable_NParCell[NLEVEL-1]; +extern int OPT__OUTPUT_PAR_MODE, OPT__OUTPUT_PAR_ADDI_ATTR, OPT__PARTICLE_COUNT, OPT__FLAG_NPAR_PATCH, FlagTable_NParPatch[NLEVEL-1], FlagTable_NParCell[NLEVEL-1]; extern double FlagTable_ParMassCell[NLEVEL-1]; extern ParOutputDens_t OPT__OUTPUT_PAR_DENS; extern int PAR_IC_FLOAT8; diff --git a/src/Auxiliary/Aux_Check_Parameter.cpp b/src/Auxiliary/Aux_Check_Parameter.cpp index a018831b4..1ab48af98 100644 --- a/src/Auxiliary/Aux_Check_Parameter.cpp +++ b/src/Auxiliary/Aux_Check_Parameter.cpp @@ -347,6 +347,10 @@ void Aux_Check_Parameter() if ( ! Aux_CheckPermission( OUTPUT_DIR, 2+1 ) ) Aux_Error( ERROR_INFO, "You do not have write and execute permissions for the \"%s\" folder set by OUTPUT_DIR !!\n", OUTPUT_DIR ); +# if ( !defined PARTICLE || !defined STORE_PAR_ACC) + if ( OPT__OUTPUT_PAR_ADDI_ATTR != 0 ) + Aux_Error( ERROR_INFO, "must enable PARTICLE and STORE_PAR_ACC for OPT__OUTPUT_PAR_ADDI_ATTR option != 0"); +# endif // general warnings diff --git a/src/Auxiliary/Aux_TakeNote.cpp b/src/Auxiliary/Aux_TakeNote.cpp index ef833f01f..5dcb93b5a 100644 --- a/src/Auxiliary/Aux_TakeNote.cpp +++ b/src/Auxiliary/Aux_TakeNote.cpp @@ -1590,70 +1590,71 @@ void Aux_TakeNote() // record the parameters of data dump fprintf( Note, "Parameters of Data Dump\n" ); fprintf( Note, "***********************************************************************************\n" ); - fprintf( Note, "OPT__OUTPUT_TOTAL % d\n", OPT__OUTPUT_TOTAL ); - fprintf( Note, "OPT__OUTPUT_PART % d\n", OPT__OUTPUT_PART ); - fprintf( Note, "OPT__OUTPUT_USER % d\n", OPT__OUTPUT_USER ); - fprintf( Note, "OPT__OUTPUT_TEXT_FORMAT_FLT %s\n", OPT__OUTPUT_TEXT_FORMAT_FLT ); - fprintf( Note, "OPT__OUTPUT_TEXT_LENGTH_INT % d\n", OPT__OUTPUT_TEXT_LENGTH_INT ); + fprintf( Note, "OPT__OUTPUT_TOTAL % d\n", OPT__OUTPUT_TOTAL ); + fprintf( Note, "OPT__OUTPUT_PART % d\n", OPT__OUTPUT_PART ); + fprintf( Note, "OPT__OUTPUT_USER % d\n", OPT__OUTPUT_USER ); + fprintf( Note, "OPT__OUTPUT_TEXT_FORMAT_FLT %s\n", OPT__OUTPUT_TEXT_FORMAT_FLT ); + fprintf( Note, "OPT__OUTPUT_TEXT_LENGTH_INT % d\n", OPT__OUTPUT_TEXT_LENGTH_INT ); # ifdef PARTICLE - fprintf( Note, "OPT__OUTPUT_PAR_MODE % d\n", OPT__OUTPUT_PAR_MODE ); + fprintf( Note, "OPT__OUTPUT_PAR_MODE % d\n", OPT__OUTPUT_PAR_MODE ); + fprintf( Note, "OPT__OUTPUT_PAR_ADDI_ATTR % d\n", OPT__OUTPUT_PAR_ADDI_ATTR ); # ifdef TRACER - fprintf( Note, "OPT__OUTPUT_PAR_MESH % d\n", OPT__OUTPUT_PAR_MESH ); + fprintf( Note, "OPT__OUTPUT_PAR_MESH % d\n", OPT__OUTPUT_PAR_MESH ); # endif # endif - fprintf( Note, "OPT__OUTPUT_BASEPS % d\n", OPT__OUTPUT_BASEPS ); - fprintf( Note, "OPT__OUTPUT_BASE % d\n", OPT__OUTPUT_BASE ); + fprintf( Note, "OPT__OUTPUT_BASEPS % d\n", OPT__OUTPUT_BASEPS ); + fprintf( Note, "OPT__OUTPUT_BASE % d\n", OPT__OUTPUT_BASE ); # ifdef GRAVITY - fprintf( Note, "OPT__OUTPUT_POT % d\n", OPT__OUTPUT_POT ); + fprintf( Note, "OPT__OUTPUT_POT % d\n", OPT__OUTPUT_POT ); # endif # ifdef PARTICLE - fprintf( Note, "OPT__OUTPUT_PAR_DENS % d\n", OPT__OUTPUT_PAR_DENS ); + fprintf( Note, "OPT__OUTPUT_PAR_DENS % d\n", OPT__OUTPUT_PAR_DENS ); # endif # ifdef MHD - fprintf( Note, "OPT__OUTPUT_CC_MAG % d\n", OPT__OUTPUT_CC_MAG ); + fprintf( Note, "OPT__OUTPUT_CC_MAG % d\n", OPT__OUTPUT_CC_MAG ); # endif # if ( MODEL == HYDRO ) - fprintf( Note, "OPT__OUTPUT_PRES % d\n", OPT__OUTPUT_PRES ); - fprintf( Note, "OPT__OUTPUT_TEMP % d\n", OPT__OUTPUT_TEMP ); - fprintf( Note, "OPT__OUTPUT_ENTR % d\n", OPT__OUTPUT_ENTR ); - fprintf( Note, "OPT__OUTPUT_CS % d\n", OPT__OUTPUT_CS ); - fprintf( Note, "OPT__OUTPUT_DIVVEL % d\n", OPT__OUTPUT_DIVVEL ); - fprintf( Note, "OPT__OUTPUT_MACH % d\n", OPT__OUTPUT_MACH ); + fprintf( Note, "OPT__OUTPUT_PRES % d\n", OPT__OUTPUT_PRES ); + fprintf( Note, "OPT__OUTPUT_TEMP % d\n", OPT__OUTPUT_TEMP ); + fprintf( Note, "OPT__OUTPUT_ENTR % d\n", OPT__OUTPUT_ENTR ); + fprintf( Note, "OPT__OUTPUT_CS % d\n", OPT__OUTPUT_CS ); + fprintf( Note, "OPT__OUTPUT_DIVVEL % d\n", OPT__OUTPUT_DIVVEL ); + fprintf( Note, "OPT__OUTPUT_MACH % d\n", OPT__OUTPUT_MACH ); # endif # ifdef MHD - fprintf( Note, "OPT__OUTPUT_DIVMAG % d\n", OPT__OUTPUT_DIVMAG ); + fprintf( Note, "OPT__OUTPUT_DIVMAG % d\n", OPT__OUTPUT_DIVMAG ); # endif - fprintf( Note, "OPT__OUTPUT_USER_FIELD % d\n", OPT__OUTPUT_USER_FIELD ); + fprintf( Note, "OPT__OUTPUT_USER_FIELD % d\n", OPT__OUTPUT_USER_FIELD ); # ifdef SRHD - fprintf( Note, "OPT__OUTPUT_3VELOCITY % d\n", OPT__OUTPUT_3VELOCITY ); - fprintf( Note, "OPT__OUTPUT_LORENTZ % d\n", OPT__OUTPUT_LORENTZ ); - fprintf( Note, "OPT__OUTPUT_ENTHALPY % d\n", OPT__OUTPUT_ENTHALPY ); + fprintf( Note, "OPT__OUTPUT_3VELOCITY % d\n", OPT__OUTPUT_3VELOCITY ); + fprintf( Note, "OPT__OUTPUT_LORENTZ % d\n", OPT__OUTPUT_LORENTZ ); + fprintf( Note, "OPT__OUTPUT_ENTHALPY % d\n", OPT__OUTPUT_ENTHALPY ); # endif // user-defined derived fields if ( OPT__OUTPUT_USER_FIELD ) { - fprintf( Note, " Number of fields % d\n", UserDerField_Num ); + fprintf( Note, " Number of fields % d\n", UserDerField_Num ); if ( UserDerField_Num > 0 ) { - fprintf( Note, " Labels " ); + fprintf( Note, " Labels " ); for (int v=0; vAdd( "OPT__OUTPUT_TEXT_LENGTH_INT",&OPT__OUTPUT_TEXT_LENGTH_INT, 12, 0, NoMax_int ); # ifdef PARTICLE ReadPara->Add( "OPT__OUTPUT_PAR_MODE", &OPT__OUTPUT_PAR_MODE, 0, 0, 2 ); + ReadPara->Add( "OPT__OUTPUT_PAR_ADDI_ATTR", &OPT__OUTPUT_PAR_ADDI_ATTR, 0, 0, 3 ); # ifdef TRACER ReadPara->Add( "OPT__OUTPUT_PAR_MESH", &OPT__OUTPUT_PAR_MESH, true, Useless_bool, Useless_bool ); # else diff --git a/src/Main/Main.cpp b/src/Main/Main.cpp index 70358820d..6eee75dd1 100644 --- a/src/Main/Main.cpp +++ b/src/Main/Main.cpp @@ -229,7 +229,7 @@ bool FFTW3_Double_OMP_Enabled, FFTW3_Single_OMP_Enabled; #ifdef PARTICLE double DT__PARVEL, DT__PARVEL_MAX, DT__PARACC; bool OPT__CK_PARTICLE, OPT__FLAG_NPAR_CELL, OPT__FLAG_PAR_MASS_CELL, OPT__FREEZE_PAR, OPT__OUTPUT_PAR_MESH, OPT__PAR_INIT_CHECK; -int OPT__OUTPUT_PAR_MODE, OPT__PARTICLE_COUNT, OPT__FLAG_NPAR_PATCH, PAR_IC_FLOAT8, PAR_IC_INT8, FlagTable_NParPatch[NLEVEL-1], FlagTable_NParCell[NLEVEL-1]; +int OPT__OUTPUT_PAR_MODE, OPT__OUTPUT_PAR_ADDI_ATTR, OPT__PARTICLE_COUNT, OPT__FLAG_NPAR_PATCH, PAR_IC_FLOAT8, PAR_IC_INT8, FlagTable_NParPatch[NLEVEL-1], FlagTable_NParCell[NLEVEL-1]; double FlagTable_ParMassCell[NLEVEL-1]; ParOutputDens_t OPT__OUTPUT_PAR_DENS; #endif diff --git a/src/Output/Output_DumpData_Total.cpp b/src/Output/Output_DumpData_Total.cpp index 6dce9b800..0cbc46a42 100644 --- a/src/Output/Output_DumpData_Total.cpp +++ b/src/Output/Output_DumpData_Total.cpp @@ -83,6 +83,15 @@ void Output_DumpData_Total( const char *FileName ) # ifdef PARTICLE long GParID_Offset = 0; // GParID = global particle index (==> unique for each particle) long NPar_EachRank[MPI_NRank]; + int par_natt_flt_addi = 0; + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 0: break; + case 1: par_natt_flt_addi = 1; break; + case 2: par_natt_flt_addi = 3; break; + case 3: par_natt_flt_addi = 4; break; + default: break; + } MPI_Allgather( &amr->Par->NPar_Active, 1, MPI_LONG, NPar_EachRank, 1, MPI_LONG, MPI_COMM_WORLD ); @@ -177,7 +186,7 @@ void Output_DumpData_Total( const char *FileName ) FileOffset_Particle = ExpectFileSize; // file offset at the beginning of particle data - ExpectFileSize += (long)PAR_NATT_FLT_STORED*amr->Par->NPar_Active_AllRank*sizeof(real_par); + ExpectFileSize += (long)( PAR_NATT_FLT_STORED + par_natt_flt_addi )*amr->Par->NPar_Active_AllRank*sizeof(real_par); ExpectFileSize += (long)PAR_NATT_INT_STORED*amr->Par->NPar_Active_AllRank*sizeof(long_par); # endif @@ -498,7 +507,7 @@ void Output_DumpData_Total( const char *FileName ) # endif # ifdef PARTICLE - const int par_natt_flt_stored = PAR_NATT_FLT_STORED; + const int par_natt_flt_stored = PAR_NATT_FLT_STORED + par_natt_flt_addi; const int par_natt_flt_user = PAR_NATT_FLT_USER; const int par_natt_int_stored = PAR_NATT_INT_STORED; const int par_natt_int_user = PAR_NATT_INT_USER; @@ -953,11 +962,13 @@ void Output_DumpData_Total( const char *FileName ) const long ParFltDataSize1v = amr->Par->NPar_Active_AllRank*sizeof(real_par); const long ParIntDataSize1v = amr->Par->NPar_Active_AllRank*sizeof(long_par); + const int par_natt_flt_stored = PAR_NATT_FLT_STORED + par_natt_flt_addi; + long NParInBuf, ParID, FileOffset_ThisVar; int NParThisPatch; // output floating-point data - for (int v=0; v = %ld != expect = %ld !!\n", FileName, ftell(File), FileOffset_ThisVar ); + if ( v > PAR_NATT_FLT_STORED ) + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 1: v = PAR_TIME; break; + default: break; + } // if ( v > PAR_NATT_FLT_STORED ), switch OPT__OUTPUT_PAR_ADDI_ATTR + for (int lv=0; lvNPatchComma[lv][1]; PID++) { @@ -1009,7 +1027,7 @@ void Output_DumpData_Total( const char *FileName ) } // if ( MPI_Rank == TargetMPIRank ) MPI_Barrier( MPI_COMM_WORLD ); - } // for (int TargetMPIRank=0; TargetMPIRank unique for each particle) long NParLv_AllRank[NLEVEL]; long MaxNPar1Lv, NParInBuf, ParID; + int par_natt_flt_addi = 0; + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 0: break; + case 1: par_natt_flt_addi = 1; break; + case 2: par_natt_flt_addi = 3; break; + case 3: par_natt_flt_addi = 4; break; + default: break; + } // prepare particle attributes mapped from mesh quantities if ( OPT__OUTPUT_PAR_MESH ) Par_Output_TracerParticle_Mesh(); @@ -1391,9 +1400,19 @@ void Output_DumpData_Total_HDF5( const char *FileName ) if ( H5_GroupID_Particle < 0 ) Aux_Error( ERROR_INFO, "failed to create the group \"%s\" !!\n", "Particle" ); // create the datasets of all particle attributes - for (int v=0; vPar->Mesh_Attr_Label[v - PAR_NATT_FLT_STORED]; + char *ParLabel; + if ( v < PAR_NATT_FLT_STORED ) + ParLabel = ParAttFltLabel[v]; + else if ( v >= PAR_NATT_FLT_STORED && v < PAR_NATT_FLT_STORED + par_natt_flt_addi ) + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 1: ParLabel = ParAttFltLabel[PAR_TIME]; break; + default: ParLabel = ParAttFltLabel[v]; break; + } + else + ParLabel = amr->Par->Mesh_Attr_Label[v - PAR_NATT_FLT_STORED - par_natt_flt_addi]; H5_SetID_ParFltData = H5Dcreate( H5_GroupID_Particle, ParLabel, H5T_GAMER_REAL_PAR, H5_SpaceID_ParData, H5P_DEFAULT, H5_DataCreatePropList, H5P_DEFAULT ); @@ -1449,7 +1468,7 @@ void Output_DumpData_Total_HDF5( const char *FileName ) // output one particle floating-point attribute at one level in one rank at a time // --> skip the last PAR_NATT_FLT_UNSTORED floating-point attributes since we do not want to store them on disk - for (int v=0; v= NPar_Lv (%ld) !!\n", lv, NParInBuf, amr->Par->NPar_Lv[lv] ); # endif - ParFltBuf1v1Lv[ NParInBuf ++ ] = ( v < PAR_NATT_FLT_STORED ) - ? amr->Par->AttributeFlt[v] [ParID] - : amr->Par->Mesh_Attr [v - PAR_NATT_FLT_STORED][ParID]; + if ( v < PAR_NATT_FLT_STORED ) + ParFltBuf1v1Lv[ NParInBuf ++ ] = amr->Par->AttributeFlt[v][ParID]; + else if ( v >= PAR_NATT_FLT_STORED && v < PAR_NATT_FLT_STORED + par_natt_flt_addi ) + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 1: ParFltBuf1v1Lv[ NParInBuf ++ ] = amr->Par->AttributeFlt[PAR_TIME][ParID]; break; + default: ParFltBuf1v1Lv[ NParInBuf ++ ] = amr->Par->AttributeFlt[v] [ParID]; break; + } + else + ParFltBuf1v1Lv[ NParInBuf ++ ] = amr->Par->Mesh_Attr[v - PAR_NATT_FLT_STORED - par_natt_flt_addi][ParID]; } // 6-3-4. write data to disk - char *ParLabel = ( v < PAR_NATT_FLT_STORED ) ? ParAttFltLabel[v] : amr->Par->Mesh_Attr_Label[v - PAR_NATT_FLT_STORED]; + char *ParLabel; + if ( v < PAR_NATT_FLT_STORED ) + ParLabel = ParAttFltLabel[v]; + else if ( v >= PAR_NATT_FLT_STORED && v < PAR_NATT_FLT_STORED + par_natt_flt_addi ) + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 1: ParLabel = ParAttFltLabel[PAR_TIME]; break; + default: ParLabel = ParAttFltLabel[v]; break; + } + else + ParLabel = amr->Par->Mesh_Attr_Label[v - PAR_NATT_FLT_STORED - par_natt_flt_addi]; H5_SetID_ParFltData = H5Dopen( H5_GroupID_Particle, ParLabel, H5P_DEFAULT ); @@ -1666,6 +1702,15 @@ void FillIn_KeyInfo( KeyInfo_t &KeyInfo, const int NFieldStored ) { const time_t CalTime = time( NULL ); // calendar time + int par_natt_flt_addi = 0; + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 0: break; + case 1: par_natt_flt_addi = 1; break; + case 2: par_natt_flt_addi = 3; break; + case 3: par_natt_flt_addi = 4; break; + default: break; + } KeyInfo.FormatVersion = 2505; KeyInfo.Model = MODEL; @@ -1695,7 +1740,7 @@ void FillIn_KeyInfo( KeyInfo_t &KeyInfo, const int NFieldStored ) KeyInfo.NMagStored = NCOMP_MAG; # ifdef PARTICLE KeyInfo.Par_NPar = amr->Par->NPar_Active_AllRank; - KeyInfo.Par_NAttFltStored = PAR_NATT_FLT_STORED; + KeyInfo.Par_NAttFltStored = PAR_NATT_FLT_STORED + par_natt_flt_addi; KeyInfo.Par_NAttIntStored = PAR_NATT_INT_STORED; # ifdef FLOAT8_PAR KeyInfo.Float8_Par = 1; @@ -2179,7 +2224,16 @@ void FillIn_SymConst( SymConst_t &SymConst ) # ifdef PARTICLE - SymConst.Par_NAttFltStored = PAR_NATT_FLT_STORED; + int par_natt_flt_addi = 0; + switch ( OPT__OUTPUT_PAR_ADDI_ATTR ) + { + case 0: break; + case 1: par_natt_flt_addi = 1; break; + case 2: par_natt_flt_addi = 3; break; + case 3: par_natt_flt_addi = 4; break; + default: break; + } + SymConst.Par_NAttFltStored = PAR_NATT_FLT_STORED + par_natt_flt_addi; SymConst.Par_NAttIntStored = PAR_NATT_INT_STORED; SymConst.Par_NType = PAR_NTYPE; # ifdef GRAVITY