/** * @brief 派生変数のファイル出力 * @param [in,out] flop 浮動小数点演算数 * @note d_p0をワークとして使用 */ void FFV::OutputDerivedVariables(double& flop) { REAL_TYPE scale = 1.0; // ステップ数 unsigned m_step = (unsigned)CurrentStep; // 時間の次元変換 REAL_TYPE m_time; if (C.Unit.File == DIMENSIONAL) { m_time = (REAL_TYPE)(CurrentTime * C.Tscale); } else { m_time = (REAL_TYPE)CurrentTime; } // ガイドセル出力 int gc_out = C.GuideOut; // 最大値と最小値 REAL_TYPE f_min, f_max, min_tmp, max_tmp, vec_min[4], vec_max[4]; REAL_TYPE minmax[2]; REAL_TYPE cio_minmax[8]; // エラーコード CIO::E_CIO_ERRORCODE ret; REAL_TYPE unit_velocity = (C.Unit.File == DIMENSIONAL) ? C.RefVelocity : 1.0; // Total Pressure if (C.varState[var_TotalP] == ON ) { fb_totalp_ (d_p0, size, &guide, d_v, d_p, v00, &flop); // convert non-dimensional to dimensional, iff file is dimensional if (C.Unit.File == DIMENSIONAL) { U.convArrayTpND2D(d_ws, d_p0, size, guide, C.RefDensity, C.RefVelocity); } else { REAL_TYPE* tp; tp = d_ws; d_ws = d_p0; d_p0 = tp; } fb_minmax_s_ (&f_min, &f_max, size, &guide, d_ws, &flop); if ( numProc > 1 ) { min_tmp = f_min; if( paraMngr->Allreduce(&min_tmp, &f_min, 1, MPI_MIN) != CPM_SUCCESS ) Exit(0); max_tmp = f_max; if( paraMngr->Allreduce(&max_tmp, &f_max, 1, MPI_MAX) != CPM_SUCCESS ) Exit(0); } minmax[0] = f_min; minmax[1] = f_max; if ( !DFI_OUT_TP ) { printf("[%d] DFI_OUT_TP Pointer Error\n",paraMngr->GetMyRankID()); Exit(-1); } ret = DFI_OUT_TP->WriteData(m_step, m_time, size, 1, guide, d_ws, minmax, true, 0, 0.0); if ( ret != CIO::E_CIO_SUCCESS ) Exit(0); } // Vorticity if (C.varState[var_Vorticity] == ON ) { rot_v_(d_wv, size, &guide, &deltaX, d_v, d_cdf, v00, &flop); REAL_TYPE vz[3]; vz[0] = vz[1] = vz[2] = 0.0; unit_velocity = (C.Unit.File == DIMENSIONAL) ? C.RefVelocity/C.RefLength : 1.0; if ( DFI_OUT_VRT->GetArrayShape() == CIO::E_CIO_NIJK ) // Vorticityの型は CIO::E_CIO_NIJK { fb_vout_nijk_(d_wo, d_wv, size, &guide, vz, &unit_velocity, &flop); fb_minmax_vex_ (vec_min, vec_max, size, &guide, v00, d_wo, &flop); } else { fb_vout_ijkn_(d_wo, d_wv, size, &guide, vz, &unit_velocity, &flop); fb_minmax_v_ (vec_min, vec_max, size, &guide, v00, d_wo, &flop); } if ( numProc > 1 ) { REAL_TYPE vmin_tmp[4] = {vec_min[0], vec_min[1], vec_min[2], vec_min[3]}; if( paraMngr->Allreduce(vmin_tmp, vec_min, 4, MPI_MIN) != CPM_SUCCESS ) Exit(0); REAL_TYPE vmax_tmp[4] = {vec_max[0], vec_max[1], vec_max[2], vec_max[3]}; if( paraMngr->Allreduce(vmax_tmp, vec_max, 4, MPI_MAX) != CPM_SUCCESS ) Exit(0); } if ( !DFI_OUT_VRT ) { printf("[%d] DFI_OUT_VRT Pointer Error\n", paraMngr->GetMyRankID()); Exit(-1); } cio_minmax[0] = vec_min[1]; ///<<< vec_u min cio_minmax[1] = vec_max[1]; ///<<< vec_u max cio_minmax[2] = vec_min[2]; ///<<< vec_v min cio_minmax[3] = vec_max[2]; ///<<< vec_v max cio_minmax[4] = vec_min[3]; ///<<< vec_w min cio_minmax[5] = vec_max[3]; ///<<< vec_w max cio_minmax[6] = vec_min[0]; ///<<< u,v,wの合成値のmin cio_minmax[7] = vec_max[0]; ///<<< u,v,wの合成値のmax ret = DFI_OUT_VRT->WriteData(m_step, m_time, size, 3, guide, d_wo, cio_minmax, true, 0, 0.0); if ( ret != CIO::E_CIO_SUCCESS ) Exit(0); } // 2nd Invariant of Velocity Gradient Tensor if (C.varState[var_Qcr] == ON ) { i2vgt_ (d_p0, size, &guide, &deltaX, d_v, d_cdf, v00, &flop); // 無次元で出力 U.copyS3D(d_ws, size, guide, d_p0, scale); fb_minmax_s_ (&f_min, &f_max, size, &guide, d_ws, &flop); if ( numProc > 1 ) { min_tmp = f_min; if( paraMngr->Allreduce(&min_tmp, &f_min, 1, MPI_MIN) != CPM_SUCCESS ) Exit(0); max_tmp = f_max; if( paraMngr->Allreduce(&max_tmp, &f_max, 1, MPI_MAX) != CPM_SUCCESS ) Exit(0); } minmax[0] = f_min; minmax[1] = f_max; if ( !DFI_OUT_I2VGT ) { printf("[%d] DFI_OUT_I2VGT Pointer Error\n", paraMngr->GetMyRankID()); Exit(-1); } ret = DFI_OUT_I2VGT->WriteData(m_step, m_time, size, 1, guide, d_ws, minmax, true, 0, 0.0); if( ret != CIO::E_CIO_SUCCESS ) Exit(0); } // Helicity if (C.varState[var_Helicity] == ON ) { helicity_(d_p0, size, &guide, &deltaX, d_v, d_cdf, v00, &flop); // 無次元で出力 U.copyS3D(d_ws, size, guide, d_p0, scale); fb_minmax_s_ (&f_min, &f_max, size, &guide, d_ws, &flop); if ( numProc > 1 ) { min_tmp = f_min; if( paraMngr->Allreduce(&min_tmp, &f_min, 1, MPI_MIN) != CPM_SUCCESS ) Exit(0); max_tmp = f_max; if( paraMngr->Allreduce(&max_tmp, &f_max, 1, MPI_MAX) != CPM_SUCCESS ) Exit(0); } minmax[0] = f_min; minmax[1] = f_max; if ( !DFI_OUT_HLT ) { printf("[%d] DFI_OUT_HLT Pointer Error\n", paraMngr->GetMyRankID()); Exit(-1); } ret = DFI_OUT_HLT->WriteData(m_step, m_time, size, 1, guide, d_ws, minmax, true, 0, 0.0); if( ret != CIO::E_CIO_SUCCESS ) Exit(0); } }
// タイムステップループの処理 int FFV::Loop(const unsigned step) { // 1 step elapse (sec) double step_start = cpm_Base::GetWTime(); double step_end; double flop_count=0.0; /// 浮動小数演算数 double avr_Var[3]; /// 平均値(速度、圧力、温度) double rms_Var[3]; /// 変動値 REAL_TYPE vMax=0.0; /// 最大速度成分 // Loop section TIMING_start(tm_loop_sct); // 時間進行 CurrentTime += DT.get_DT(); // 戻り値はdouble CurrentStep++; // 参照座標速度をv00に保持する copyV00fromRF(CurrentTime); // モニタークラスに参照速度を渡す if (C.SamplingMode == ON) MO.setV00(v00); // 速度成分の最大値 TIMING_start(tm_vmax); flop_count = 0.0; find_vmax_(&vMax, size, &guide, v00, d_v, &flop_count); TIMING_stop(tm_vmax, flop_count); if ( numProc > 1 ) { TIMING_start(tm_vmax_comm); REAL_TYPE vMax_tmp = vMax; if ( paraMngr->Allreduce(&vMax_tmp, &vMax, 1, MPI_MAX) != CPM_SUCCESS ) Exit(0); TIMING_stop( tm_vmax_comm, 2.0*numProc*sizeof(REAL_TYPE) ); // 双方向 x ノード数 } // Flow if ( C.KindOfSolver != SOLID_CONDUCTION ) { TIMING_start(tm_flow_sct); switch (C.AlgorithmF) { case Flow_FS_EE_EE: case Flow_FS_AB2: case Flow_FS_AB_CN: if (C.Mode.ShapeAprx == BINARY) { NS_FS_E_Binary(); } else if (C.Mode.ShapeAprx == CUT_INFO) { NS_FS_E_CDS(); } break; case Flow_FS_RK_CN: break; default: break; } TIMING_stop(tm_flow_sct, 0.0); } // Heat if ( C.isHeatProblem() ) { TIMING_start(tm_heat_sct); PS_Binary(); TIMING_stop(tm_heat_sct, 0.0); } // Interface Equation if ( C.BasicEqs == INCMP_2PHASE ) { TIMING_start(tm_vof_sct); //IF_TRP_VOF(); TIMING_stop(tm_vof_sct, 0.0); } // >>> ステップループのユーティリティ TIMING_start(tm_loop_uty_sct); // >>> ステップループのユーティリティ 1 TIMING_start(tm_loop_uty_sct_1); // 時間平均値操作 if ( (C.Mode.Average == ON) && C.Interval[Control::tg_average].isStarted(CurrentStep, CurrentTime)) { TIMING_start(tm_average_time); flop_count=0.0; Averaging(flop_count); TIMING_stop(tm_average_time, flop_count); } // 空間平均値操作と変動量 TIMING_start(tm_stat_space); flop_count=0.0; for (int i=0; i<3; i++) { avr_Var[i] = 0.0; rms_Var[i] = 0.0; } VariationSpace(avr_Var, rms_Var, flop_count); TIMING_stop(tm_stat_space, flop_count); if ( numProc > 1 ) { /// var_Velocity=0, > FB_Define.h /// var_Pressure, /// var_Temperature, double src[6], dst[6]; // Vel, Prs, Tempで3*2 TIMING_start(tm_stat_space_comm); for (int n=0; n<3; n++) { src[n] = avr_Var[n]; src[n+3] = rms_Var[n]; } if ( paraMngr->Allreduce(src, dst, 6, MPI_SUM) != CPM_SUCCESS) Exit(0); // 変数 x (平均値+変動値) for (int n=0; n<3; n++) { avr_Var[n] = dst[n]; rms_Var[n] = dst[n+3]; } TIMING_stop(tm_stat_space_comm, 2.0*numProc*6.0*2.0*sizeof(double) ); // 双方向 x ノード数 x 変数 } avr_Var[var_Velocity] /= (double)G_Acell; // 速度の空間平均 avr_Var[var_Pressure] /= (double)G_Acell; // 圧力の空間平均 rms_Var[var_Velocity] /= (double)G_Acell; // 速度の変動量 rms_Var[var_Pressure] /= (double)G_Acell; // 圧力の変動量 rms_Var[var_Velocity] = sqrt(rms_Var[var_Velocity]); rms_Var[var_Pressure] = sqrt(rms_Var[var_Pressure]); if ( C.isHeatProblem() ) { avr_Var[var_Temperature] /= (double)G_Acell; // 温度の空間平均 rms_Var[var_Temperature] /= (double)G_Acell; // 温度の変動量 rms_Var[var_Temperature] = sqrt(rms_Var[var_Temperature]); } // <<< ステップループのユーティリティ 1 TIMING_stop(tm_loop_uty_sct_1, 0.0); // 1ステップ後のモニタ処理 ------------------------------- // >>> ステップループのユーティリティ 2 TIMING_start(tm_loop_uty_sct_2); // Historyクラスのタイムスタンプを更新 H->updateTimeStamp(CurrentStep, (REAL_TYPE)CurrentTime, vMax); // 瞬時値のデータ出力 if ( C.Hide.PM_Test == OFF ) { // 通常 if ( C.Interval[Control::tg_basic].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_file_out); flop_count=0.0; OutputBasicVariables(flop_count); TIMING_stop(tm_file_out, flop_count); } if ( C.Interval[Control::tg_derived].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_file_out); flop_count=0.0; OutputDerivedVariables(flop_count); TIMING_stop(tm_file_out, flop_count); } // 最終ステップ if ( C.Interval[Control::tg_compute].isLast(CurrentStep, CurrentTime) ) { // 指定間隔の出力がない場合のみ(重複を避ける) if ( !C.Interval[Control::tg_basic].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_file_out); flop_count=0.0; OutputBasicVariables(flop_count); TIMING_stop(tm_file_out, flop_count); } if ( !C.Interval[Control::tg_derived].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_file_out); flop_count=0.0; OutputDerivedVariables(flop_count); TIMING_stop(tm_file_out, flop_count); } } } // 平均値のデータ出力 if (C.Mode.Average == ON) { // 開始時刻を過ぎているか if ( C.Interval[Control::tg_average].isStarted(CurrentStep, CurrentTime) ) { // 通常 if ( C.Interval[Control::tg_average].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_file_out); flop_count=0.0; OutputAveragedVarables(flop_count); TIMING_stop(tm_file_out, flop_count); } // 最終ステップ if ( C.Interval[Control::tg_compute].isLast(CurrentStep, CurrentTime) ) { // 指定間隔の出力がない場合のみ(重複を避ける) if ( !C.Interval[Control::tg_average].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_file_out); flop_count=0.0; OutputAveragedVarables(flop_count); TIMING_stop(tm_file_out, flop_count); } } } } if (C.varState[var_TotalP] == ON ) { TIMING_start(tm_total_prs); flop_count=0.0; fb_totalp_ (d_p0, size, &guide, d_v, d_p, v00, &flop_count); TIMING_stop(tm_total_prs, flop_count); } // サンプリング履歴 if ( (C.SamplingMode == ON) && C.Interval[Control::tg_sampled].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_sampling); MO.sampling(); TIMING_stop(tm_sampling, 0.0); TIMING_start(tm_hstry_sampling); MO.print(CurrentStep, (REAL_TYPE)CurrentTime); TIMING_stop(tm_hstry_sampling, 0.0); } // 1 step elapse step_end = cpm_Base::GetWTime() - step_start; // 基本履歴情報をコンソールに出力 if ( C.Mode.Log_Base == ON) { if ( C.Interval[Control::tg_console].isTriggered(CurrentStep, CurrentTime) ) { TIMING_start(tm_hstry_stdout); Hostonly_ { H->printHistory(stdout, avr_Var, rms_Var, IC, &C, step_end, true); if ( C.Mode.CCNV == ON ) { H->printCCNV(avr_Var, rms_Var, IC, &C, step_end); } } TIMING_stop(tm_hstry_stdout, 0.0); } }