logger.f90 Source File


Files dependent on this one

sourcefile~~logger.f90~~AfferentGraph sourcefile~logger.f90 logger.f90 sourcefile~abl.f90 abl.f90 sourcefile~abl.f90->sourcefile~logger.f90 sourcefile~backend.f90~3 backend.f90 sourcefile~abl.f90->sourcefile~backend.f90~3 sourcefile~common.f90~3 common.f90 sourcefile~abl.f90->sourcefile~common.f90~3 sourcefile~config.f90 config.f90 sourcefile~abl.f90->sourcefile~config.f90 sourcefile~les.f90 les.f90 sourcefile~abl.f90->sourcefile~les.f90 sourcefile~mesh.f90 mesh.f90 sourcefile~abl.f90->sourcefile~mesh.f90 sourcefile~allocator.f90~2 allocator.f90 sourcefile~abl.f90->sourcefile~allocator.f90~2 sourcefile~field.f90 field.f90 sourcefile~abl.f90->sourcefile~field.f90 sourcefile~abl.f90~2 abl.f90 sourcefile~abl.f90~2->sourcefile~logger.f90 sourcefile~abl.f90~2->sourcefile~abl.f90 sourcefile~abl.f90~2->sourcefile~backend.f90~3 sourcefile~base_case.f90 base_case.f90 sourcefile~abl.f90~2->sourcefile~base_case.f90 sourcefile~abl.f90~2->sourcefile~common.f90~3 sourcefile~abl.f90~2->sourcefile~config.f90 sourcefile~diagnostics.f90 diagnostics.f90 sourcefile~abl.f90~2->sourcefile~diagnostics.f90 sourcefile~abl.f90~2->sourcefile~mesh.f90 sourcefile~abl.f90~2->sourcefile~allocator.f90~2 sourcefile~abl.f90~2->sourcefile~field.f90 sourcefile~adm.f90 adm.f90 sourcefile~adm.f90->sourcefile~logger.f90 sourcefile~adm.f90->sourcefile~backend.f90~3 sourcefile~adm.f90->sourcefile~common.f90~3 sourcefile~io_session.f90 io_session.f90 sourcefile~adm.f90->sourcefile~io_session.f90 sourcefile~adm.f90->sourcefile~mesh.f90 sourcefile~scalar_series.f90 scalar_series.f90 sourcefile~adm.f90->sourcefile~scalar_series.f90 sourcefile~adm.f90->sourcefile~allocator.f90~2 sourcefile~adm.f90->sourcefile~field.f90 sourcefile~turbine_model.f90 turbine_model.f90 sourcefile~adm.f90->sourcefile~turbine_model.f90 sourcefile~allocator.f90~3 allocator.f90 sourcefile~allocator.f90~3->sourcefile~logger.f90 sourcefile~allocator.f90~3->sourcefile~common.f90~3 sourcefile~allocator.f90~3->sourcefile~mesh.f90 sourcefile~allocator.f90~3->sourcefile~allocator.f90~2 sourcefile~allocator.f90~3->sourcefile~field.f90 sourcefile~backend.f90 backend.f90 sourcefile~backend.f90->sourcefile~logger.f90 sourcefile~backend.f90->sourcefile~backend.f90~3 sourcefile~backend.f90->sourcefile~common.f90~3 sourcefile~backend.f90->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~3 poisson_fft.f90 sourcefile~backend.f90->sourcefile~poisson_fft.f90~3 sourcefile~sendrecv.f90~2 sendrecv.f90 sourcefile~backend.f90->sourcefile~sendrecv.f90~2 sourcefile~tdsops.f90~2 tdsops.f90 sourcefile~backend.f90->sourcefile~tdsops.f90~2 sourcefile~backend.f90->sourcefile~allocator.f90~2 sourcefile~exec_dist.f90~3 exec_dist.f90 sourcefile~backend.f90->sourcefile~exec_dist.f90~3 sourcefile~exec_thom.f90~3 exec_thom.f90 sourcefile~backend.f90->sourcefile~exec_thom.f90~3 sourcefile~backend.f90->sourcefile~field.f90 sourcefile~ordering.f90 ordering.f90 sourcefile~backend.f90->sourcefile~ordering.f90 sourcefile~backend.f90~2 backend.f90 sourcefile~backend.f90~2->sourcefile~logger.f90 sourcefile~backend.f90~2->sourcefile~backend.f90~3 sourcefile~backend.f90~2->sourcefile~common.f90~3 sourcefile~common.f90~4 common.f90 sourcefile~backend.f90~2->sourcefile~common.f90~4 sourcefile~exec_dist.f90 exec_dist.f90 sourcefile~backend.f90~2->sourcefile~exec_dist.f90 sourcefile~backend.f90~2->sourcefile~mesh.f90 sourcefile~backend.f90~2->sourcefile~tdsops.f90~2 sourcefile~backend.f90~2->sourcefile~allocator.f90~2 sourcefile~exec_thom.f90~2 exec_thom.f90 sourcefile~backend.f90~2->sourcefile~exec_thom.f90~2 sourcefile~backend.f90~2->sourcefile~field.f90 sourcefile~fieldops.f90~2 fieldops.f90 sourcefile~backend.f90~2->sourcefile~fieldops.f90~2 sourcefile~sendrecv.f90 sendrecv.f90 sourcefile~backend.f90~2->sourcefile~sendrecv.f90 sourcefile~tdsops.f90~3 tdsops.f90 sourcefile~backend.f90~2->sourcefile~tdsops.f90~3 sourcefile~backend.f90~3->sourcefile~logger.f90 sourcefile~backend.f90~3->sourcefile~common.f90~3 sourcefile~backend.f90~3->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~2 poisson_fft.f90 sourcefile~backend.f90~3->sourcefile~poisson_fft.f90~2 sourcefile~backend.f90~3->sourcefile~tdsops.f90~2 sourcefile~backend.f90~3->sourcefile~allocator.f90~2 sourcefile~backend.f90~3->sourcefile~field.f90 sourcefile~backend.f90~4 backend.f90 sourcefile~backend.f90~4->sourcefile~logger.f90 sourcefile~backend.f90~4->sourcefile~backend.f90~3 sourcefile~backend.f90~4->sourcefile~common.f90~3 sourcefile~errors.f90 errors.f90 sourcefile~backend.f90~4->sourcefile~errors.f90 sourcefile~backend.f90~4->sourcefile~mesh.f90 sourcefile~poisson_fft.f90 poisson_fft.f90 sourcefile~backend.f90~4->sourcefile~poisson_fft.f90 sourcefile~sendrecv.f90~3 sendrecv.f90 sourcefile~backend.f90~4->sourcefile~sendrecv.f90~3 sourcefile~backend.f90~4->sourcefile~tdsops.f90~2 sourcefile~allocator.f90 allocator.f90 sourcefile~backend.f90~4->sourcefile~allocator.f90 sourcefile~backend.f90~4->sourcefile~allocator.f90~2 sourcefile~distributed.f90~3 distributed.f90 sourcefile~backend.f90~4->sourcefile~distributed.f90~3 sourcefile~exec_dist.f90~2 exec_dist.f90 sourcefile~backend.f90~4->sourcefile~exec_dist.f90~2 sourcefile~exec_thom.f90 exec_thom.f90 sourcefile~backend.f90~4->sourcefile~exec_thom.f90 sourcefile~backend.f90~4->sourcefile~field.f90 sourcefile~fieldops.f90 fieldops.f90 sourcefile~backend.f90~4->sourcefile~fieldops.f90 sourcefile~reorder.f90 reorder.f90 sourcefile~backend.f90~4->sourcefile~reorder.f90 sourcefile~tdsops.f90 tdsops.f90 sourcefile~backend.f90~4->sourcefile~tdsops.f90 sourcefile~base_case.f90->sourcefile~logger.f90 sourcefile~base_case.f90->sourcefile~backend.f90~3 sourcefile~base_case.f90->sourcefile~common.f90~3 sourcefile~base_case.f90->sourcefile~config.f90 sourcefile~base_case.f90->sourcefile~mesh.f90 sourcefile~monitoring.f90 monitoring.f90 sourcefile~base_case.f90->sourcefile~monitoring.f90 sourcefile~postprocess.f90 postprocess.f90 sourcefile~base_case.f90->sourcefile~postprocess.f90 sourcefile~solver.f90 solver.f90 sourcefile~base_case.f90->sourcefile~solver.f90 sourcefile~base_case.f90->sourcefile~allocator.f90~2 sourcefile~base_case.f90->sourcefile~field.f90 sourcefile~io_manager.f90 io_manager.f90 sourcefile~base_case.f90->sourcefile~io_manager.f90 sourcefile~channel.f90 channel.f90 sourcefile~channel.f90->sourcefile~logger.f90 sourcefile~channel.f90->sourcefile~backend.f90~3 sourcefile~channel.f90->sourcefile~base_case.f90 sourcefile~channel.f90->sourcefile~common.f90~3 sourcefile~channel.f90->sourcefile~config.f90 sourcefile~channel.f90->sourcefile~mesh.f90 sourcefile~channel.f90->sourcefile~solver.f90 sourcefile~channel.f90->sourcefile~allocator.f90~2 sourcefile~channel.f90->sourcefile~field.f90 sourcefile~checkpoint_manager.f90 checkpoint_manager.f90 sourcefile~checkpoint_manager.f90->sourcefile~logger.f90 sourcefile~checkpoint_manager.f90->sourcefile~common.f90~3 sourcefile~checkpoint_manager.f90->sourcefile~config.f90 sourcefile~io.f90 io.f90 sourcefile~checkpoint_manager.f90->sourcefile~io.f90 sourcefile~io_field_utils.f90 io_field_utils.f90 sourcefile~checkpoint_manager.f90->sourcefile~io_field_utils.f90 sourcefile~checkpoint_manager.f90->sourcefile~io_session.f90 sourcefile~checkpoint_manager.f90->sourcefile~solver.f90 sourcefile~stats.f90 stats.f90 sourcefile~checkpoint_manager.f90->sourcefile~stats.f90 sourcefile~checkpoint_state.f90 checkpoint_state.f90 sourcefile~checkpoint_manager.f90->sourcefile~checkpoint_state.f90 sourcefile~checkpoint_manager.f90->sourcefile~field.f90 sourcefile~common.f90~3->sourcefile~logger.f90 sourcefile~common.f90~4->sourcefile~logger.f90 sourcefile~common.f90~4->sourcefile~common.f90~3 sourcefile~config.f90->sourcefile~logger.f90 sourcefile~config.f90->sourcefile~common.f90~3 sourcefile~cylinder.f90 cylinder.f90 sourcefile~cylinder.f90->sourcefile~logger.f90 sourcefile~cylinder.f90->sourcefile~backend.f90~3 sourcefile~cylinder.f90->sourcefile~base_case.f90 sourcefile~cylinder.f90->sourcefile~common.f90~3 sourcefile~cylinder.f90->sourcefile~config.f90 sourcefile~cylinder.f90->sourcefile~mesh.f90 sourcefile~cylinder.f90->sourcefile~solver.f90 sourcefile~cylinder.f90->sourcefile~allocator.f90~2 sourcefile~cylinder.f90->sourcefile~field.f90 sourcefile~decomp_2decompfft.f90 decomp_2decompfft.f90 sourcefile~decomp_2decompfft.f90->sourcefile~logger.f90 sourcefile~mesh_content.f90 mesh_content.f90 sourcefile~decomp_2decompfft.f90->sourcefile~mesh_content.f90 sourcefile~decomp_dummy.f90 decomp_dummy.f90 sourcefile~decomp_dummy.f90->sourcefile~logger.f90 sourcefile~decomp_dummy.f90->sourcefile~mesh_content.f90 sourcefile~diagnostics.f90->sourcefile~logger.f90 sourcefile~diagnostics.f90->sourcefile~backend.f90~3 sourcefile~diagnostics.f90->sourcefile~common.f90~3 sourcefile~diagnostics.f90->sourcefile~config.f90 sourcefile~diagnostics.f90->sourcefile~les.f90 sourcefile~diagnostics.f90->sourcefile~mesh.f90 sourcefile~diagnostics.f90->sourcefile~field.f90 sourcefile~errors.f90->sourcefile~logger.f90 sourcefile~exec_dist.f90->sourcefile~logger.f90 sourcefile~exec_dist.f90->sourcefile~common.f90~3 sourcefile~exec_dist.f90->sourcefile~common.f90~4 sourcefile~distributed.f90 distributed.f90 sourcefile~exec_dist.f90->sourcefile~distributed.f90 sourcefile~exec_dist.f90->sourcefile~sendrecv.f90 sourcefile~exec_dist.f90->sourcefile~tdsops.f90~3 sourcefile~generic.f90 generic.f90 sourcefile~generic.f90->sourcefile~logger.f90 sourcefile~generic.f90->sourcefile~backend.f90~3 sourcefile~generic.f90->sourcefile~base_case.f90 sourcefile~generic.f90->sourcefile~common.f90~3 sourcefile~generic.f90->sourcefile~mesh.f90 sourcefile~generic.f90->sourcefile~solver.f90 sourcefile~generic.f90->sourcefile~allocator.f90~2 sourcefile~generic.f90->sourcefile~field.f90 sourcefile~ibm.f90 ibm.f90 sourcefile~ibm.f90->sourcefile~logger.f90 sourcefile~ibm.f90->sourcefile~backend.f90~3 sourcefile~ibm.f90->sourcefile~common.f90~3 sourcefile~ibm.f90->sourcefile~io_session.f90 sourcefile~ibm.f90->sourcefile~mesh.f90 sourcefile~ibm.f90->sourcefile~allocator.f90~2 sourcefile~ibm.f90->sourcefile~field.f90 sourcefile~io.f90->sourcefile~logger.f90 sourcefile~io.f90->sourcefile~backend.f90~3 sourcefile~io.f90->sourcefile~common.f90~3 sourcefile~io.f90->sourcefile~field.f90 sourcefile~io_base.f90 io_base.f90 sourcefile~io.f90->sourcefile~io_base.f90 sourcefile~io.f90~2 io.f90 sourcefile~io.f90~2->sourcefile~logger.f90 sourcefile~io.f90~2->sourcefile~backend.f90~3 sourcefile~io.f90~2->sourcefile~common.f90~3 sourcefile~io.f90~2->sourcefile~field.f90 sourcefile~io.f90~2->sourcefile~io_base.f90 sourcefile~io_field_utils.f90->sourcefile~logger.f90 sourcefile~io_field_utils.f90->sourcefile~common.f90~3 sourcefile~io_field_utils.f90->sourcefile~solver.f90 sourcefile~io_field_utils.f90->sourcefile~field.f90 sourcefile~io_field_utils.f90->sourcefile~io_base.f90 sourcefile~io_session.f90->sourcefile~logger.f90 sourcefile~io_session.f90->sourcefile~backend.f90~3 sourcefile~io_session.f90->sourcefile~common.f90~3 sourcefile~io_session.f90->sourcefile~io.f90 sourcefile~io_session.f90->sourcefile~field.f90 sourcefile~io_session.f90->sourcefile~io_base.f90 sourcefile~les.f90->sourcefile~logger.f90 sourcefile~les.f90->sourcefile~backend.f90~3 sourcefile~les.f90->sourcefile~common.f90~3 sourcefile~les.f90->sourcefile~config.f90 sourcefile~les.f90->sourcefile~mesh.f90 sourcefile~les.f90->sourcefile~tdsops.f90~2 sourcefile~les.f90->sourcefile~field.f90 sourcefile~mesh.f90->sourcefile~logger.f90 sourcefile~mesh.f90->sourcefile~common.f90~3 sourcefile~mesh.f90->sourcefile~decomp_dummy.f90 sourcefile~mesh.f90->sourcefile~mesh_content.f90 sourcefile~mesh.f90->sourcefile~field.f90 sourcefile~mesh_content.f90->sourcefile~logger.f90 sourcefile~mesh_content.f90->sourcefile~common.f90~3 sourcefile~monitoring.f90->sourcefile~logger.f90 sourcefile~monitoring.f90->sourcefile~common.f90~3 sourcefile~monitoring.f90->sourcefile~scalar_series.f90 sourcefile~monitoring.f90->sourcefile~solver.f90 sourcefile~monitoring.f90->sourcefile~field.f90 sourcefile~poisson_fft.f90->sourcefile~logger.f90 sourcefile~poisson_fft.f90->sourcefile~common.f90~3 sourcefile~poisson_fft.f90->sourcefile~errors.f90 sourcefile~poisson_fft.f90->sourcefile~mesh.f90 sourcefile~poisson_fft.f90->sourcefile~poisson_fft.f90~2 sourcefile~poisson_fft.f90->sourcefile~sendrecv.f90~3 sourcefile~poisson_fft.f90->sourcefile~tdsops.f90~2 sourcefile~poisson_fft.f90->sourcefile~allocator.f90 sourcefile~poisson_fft.f90->sourcefile~field.f90 sourcefile~spectral_processing.f90 spectral_processing.f90 sourcefile~poisson_fft.f90->sourcefile~spectral_processing.f90 sourcefile~poisson_fft.f90~2->sourcefile~logger.f90 sourcefile~poisson_fft.f90~2->sourcefile~common.f90~3 sourcefile~poisson_fft.f90~2->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~2->sourcefile~tdsops.f90~2 sourcefile~poisson_fft.f90~2->sourcefile~field.f90 sourcefile~poisson_fft.f90~3->sourcefile~logger.f90 sourcefile~poisson_fft.f90~3->sourcefile~common.f90~3 sourcefile~poisson_fft.f90~3->sourcefile~mesh.f90 sourcefile~poisson_fft.f90~3->sourcefile~poisson_fft.f90~2 sourcefile~spectral_processing.f90~2 spectral_processing.f90 sourcefile~poisson_fft.f90~3->sourcefile~spectral_processing.f90~2 sourcefile~poisson_fft.f90~3->sourcefile~tdsops.f90~2 sourcefile~poisson_fft.f90~3->sourcefile~field.f90 sourcefile~postprocess.f90->sourcefile~logger.f90 sourcefile~postprocess.f90->sourcefile~common.f90~3 sourcefile~postprocess.f90->sourcefile~solver.f90 sourcefile~postprocess.f90->sourcefile~field.f90 sourcefile~scalar_series.f90->sourcefile~logger.f90 sourcefile~scalar_series.f90->sourcefile~common.f90~3 sourcefile~sendrecv.f90~2->sourcefile~logger.f90 sourcefile~sendrecv.f90~2->sourcefile~common.f90~3 sourcefile~sendrecv.f90~3->sourcefile~logger.f90 sourcefile~sendrecv.f90~3->sourcefile~common.f90~3 sourcefile~sendrecv.f90~3->sourcefile~errors.f90 sourcefile~setup.f90 setup.f90 sourcefile~setup.f90->sourcefile~logger.f90 sourcefile~setup.f90->sourcefile~allocator.f90~3 sourcefile~setup.f90->sourcefile~backend.f90 sourcefile~setup.f90->sourcefile~backend.f90~2 sourcefile~setup.f90->sourcefile~backend.f90~3 sourcefile~setup.f90->sourcefile~backend.f90~4 sourcefile~setup.f90->sourcefile~common.f90~3 sourcefile~setup.f90->sourcefile~common.f90~4 sourcefile~setup.f90->sourcefile~errors.f90 sourcefile~setup.f90->sourcefile~mesh.f90 sourcefile~setup.f90->sourcefile~allocator.f90 sourcefile~setup.f90->sourcefile~allocator.f90~2 sourcefile~snapshot_manager.f90 snapshot_manager.f90 sourcefile~snapshot_manager.f90->sourcefile~logger.f90 sourcefile~snapshot_manager.f90->sourcefile~common.f90~3 sourcefile~snapshot_manager.f90->sourcefile~config.f90 sourcefile~snapshot_manager.f90->sourcefile~io.f90 sourcefile~snapshot_manager.f90->sourcefile~io_field_utils.f90 sourcefile~snapshot_manager.f90->sourcefile~io_session.f90 sourcefile~snapshot_manager.f90->sourcefile~solver.f90 sourcefile~snapshot_manager.f90->sourcefile~field.f90 sourcefile~solver.f90->sourcefile~logger.f90 sourcefile~solver.f90->sourcefile~backend.f90~3 sourcefile~solver.f90->sourcefile~common.f90~3 sourcefile~solver.f90->sourcefile~config.f90 sourcefile~solver.f90->sourcefile~ibm.f90 sourcefile~solver.f90->sourcefile~les.f90 sourcefile~solver.f90->sourcefile~mesh.f90 sourcefile~solver.f90->sourcefile~tdsops.f90~2 sourcefile~time_integrator.f90 time_integrator.f90 sourcefile~solver.f90->sourcefile~time_integrator.f90 sourcefile~vector_calculus.f90 vector_calculus.f90 sourcefile~solver.f90->sourcefile~vector_calculus.f90 sourcefile~solver.f90->sourcefile~allocator.f90~2 sourcefile~solver.f90->sourcefile~field.f90 sourcefile~spectral_processing.f90~2->sourcefile~logger.f90 sourcefile~spectral_processing.f90~2->sourcefile~common.f90~3 sourcefile~stats.f90->sourcefile~logger.f90 sourcefile~stats.f90->sourcefile~common.f90~3 sourcefile~stats.f90->sourcefile~config.f90 sourcefile~stats.f90->sourcefile~io_session.f90 sourcefile~stats.f90->sourcefile~solver.f90 sourcefile~stats.f90->sourcefile~field.f90 sourcefile~tdsops.f90~2->sourcefile~logger.f90 sourcefile~tdsops.f90~2->sourcefile~common.f90~3 sourcefile~tgv.f90 tgv.f90 sourcefile~tgv.f90->sourcefile~logger.f90 sourcefile~tgv.f90->sourcefile~backend.f90~3 sourcefile~tgv.f90->sourcefile~base_case.f90 sourcefile~tgv.f90->sourcefile~common.f90~3 sourcefile~tgv.f90->sourcefile~mesh.f90 sourcefile~tgv.f90->sourcefile~solver.f90 sourcefile~tgv.f90->sourcefile~allocator.f90~2 sourcefile~tgv.f90->sourcefile~field.f90 sourcefile~time_integrator.f90->sourcefile~logger.f90 sourcefile~time_integrator.f90->sourcefile~backend.f90~3 sourcefile~time_integrator.f90->sourcefile~common.f90~3 sourcefile~time_integrator.f90->sourcefile~allocator.f90~2 sourcefile~time_integrator.f90->sourcefile~field.f90 sourcefile~vector_calculus.f90->sourcefile~logger.f90 sourcefile~vector_calculus.f90->sourcefile~backend.f90~3 sourcefile~vector_calculus.f90->sourcefile~common.f90~3 sourcefile~vector_calculus.f90->sourcefile~tdsops.f90~2 sourcefile~vector_calculus.f90->sourcefile~allocator.f90~2 sourcefile~vector_calculus.f90->sourcefile~field.f90 sourcefile~wind_turbine.f90 wind_turbine.f90 sourcefile~wind_turbine.f90->sourcefile~logger.f90 sourcefile~wind_turbine.f90->sourcefile~adm.f90 sourcefile~wind_turbine.f90->sourcefile~backend.f90~3 sourcefile~wind_turbine.f90->sourcefile~base_case.f90 sourcefile~wind_turbine.f90->sourcefile~common.f90~3 sourcefile~wind_turbine.f90->sourcefile~config.f90 sourcefile~wind_turbine.f90->sourcefile~mesh.f90 sourcefile~wind_turbine.f90->sourcefile~solver.f90 sourcefile~wind_turbine.f90->sourcefile~allocator.f90~2 sourcefile~wind_turbine.f90->sourcefile~field.f90 sourcefile~turbine_dummy.f90 turbine_dummy.f90 sourcefile~wind_turbine.f90->sourcefile~turbine_dummy.f90 sourcefile~wind_turbine.f90->sourcefile~turbine_model.f90 sourcefile~xcompact.f90 xcompact.f90 sourcefile~xcompact.f90->sourcefile~logger.f90 sourcefile~xcompact.f90->sourcefile~abl.f90~2 sourcefile~xcompact.f90->sourcefile~base_case.f90 sourcefile~xcompact.f90->sourcefile~channel.f90 sourcefile~xcompact.f90->sourcefile~common.f90~3 sourcefile~xcompact.f90->sourcefile~config.f90 sourcefile~xcompact.f90->sourcefile~cylinder.f90 sourcefile~xcompact.f90->sourcefile~generic.f90 sourcefile~xcompact.f90->sourcefile~mesh.f90 sourcefile~xcompact.f90->sourcefile~setup.f90 sourcefile~xcompact.f90->sourcefile~tgv.f90 sourcefile~xcompact.f90->sourcefile~wind_turbine.f90 sourcefile~allocator.f90->sourcefile~common.f90~3 sourcefile~allocator.f90->sourcefile~mesh.f90 sourcefile~allocator.f90->sourcefile~allocator.f90~2 sourcefile~allocator.f90->sourcefile~field.f90 sourcefile~allocator.f90~2->sourcefile~common.f90~3 sourcefile~allocator.f90~2->sourcefile~field.f90 sourcefile~checkpoint_state.f90->sourcefile~io_session.f90 sourcefile~distributed.f90->sourcefile~common.f90~3 sourcefile~distributed.f90->sourcefile~common.f90~4 sourcefile~distributed.f90~2 distributed.f90 sourcefile~distributed.f90~2->sourcefile~common.f90~3 sourcefile~distributed.f90~3->sourcefile~common.f90~3 sourcefile~exec_dist.f90~2->sourcefile~common.f90~3 sourcefile~exec_dist.f90~2->sourcefile~sendrecv.f90~3 sourcefile~exec_dist.f90~2->sourcefile~distributed.f90~3 sourcefile~exec_dist.f90~2->sourcefile~tdsops.f90 sourcefile~exec_dist.f90~3->sourcefile~common.f90~3 sourcefile~exec_dist.f90~3->sourcefile~sendrecv.f90~2 sourcefile~exec_dist.f90~3->sourcefile~tdsops.f90~2 sourcefile~exec_dist.f90~3->sourcefile~distributed.f90~2 sourcefile~exec_thom.f90->sourcefile~common.f90~3 sourcefile~exec_thom.f90->sourcefile~tdsops.f90 sourcefile~thomas.f90~2 thomas.f90 sourcefile~exec_thom.f90->sourcefile~thomas.f90~2 sourcefile~exec_thom.f90~2->sourcefile~common.f90~3 sourcefile~exec_thom.f90~2->sourcefile~tdsops.f90~3 sourcefile~thomas.f90 thomas.f90 sourcefile~exec_thom.f90~2->sourcefile~thomas.f90 sourcefile~exec_thom.f90~3->sourcefile~common.f90~3 sourcefile~exec_thom.f90~3->sourcefile~tdsops.f90~2 sourcefile~thomas.f90~3 thomas.f90 sourcefile~exec_thom.f90~3->sourcefile~thomas.f90~3 sourcefile~field.f90->sourcefile~common.f90~3 sourcefile~fieldops.f90->sourcefile~common.f90~3 sourcefile~fieldops.f90~2->sourcefile~common.f90~3 sourcefile~fieldops.f90~2->sourcefile~common.f90~4 sourcefile~io_base.f90->sourcefile~backend.f90~3 sourcefile~io_base.f90->sourcefile~common.f90~3 sourcefile~io_base.f90->sourcefile~field.f90 sourcefile~io_manager.f90->sourcefile~checkpoint_manager.f90 sourcefile~io_manager.f90->sourcefile~snapshot_manager.f90 sourcefile~io_manager.f90->sourcefile~solver.f90 sourcefile~io_manager.f90->sourcefile~stats.f90 sourcefile~io_manager.f90->sourcefile~checkpoint_state.f90 sourcefile~ordering.f90->sourcefile~common.f90~3 sourcefile~reorder.f90->sourcefile~common.f90~3 sourcefile~sendrecv.f90->sourcefile~common.f90~3 sourcefile~sendrecv.f90->sourcefile~common.f90~4 sourcefile~spectral_processing.f90->sourcefile~common.f90~3 sourcefile~tdsops.f90->sourcefile~common.f90~3 sourcefile~tdsops.f90->sourcefile~tdsops.f90~2 sourcefile~tdsops.f90~3->sourcefile~common.f90~3 sourcefile~tdsops.f90~3->sourcefile~common.f90~4 sourcefile~tdsops.f90~3->sourcefile~tdsops.f90~2 sourcefile~thomas.f90->sourcefile~common.f90~3 sourcefile~thomas.f90->sourcefile~common.f90~4 sourcefile~thomas.f90~2->sourcefile~common.f90~3 sourcefile~thomas.f90~3->sourcefile~common.f90~3 sourcefile~turbine_dummy.f90->sourcefile~backend.f90~3 sourcefile~turbine_dummy.f90->sourcefile~common.f90~3 sourcefile~turbine_dummy.f90->sourcefile~io_session.f90 sourcefile~turbine_dummy.f90->sourcefile~mesh.f90 sourcefile~turbine_dummy.f90->sourcefile~allocator.f90~2 sourcefile~turbine_dummy.f90->sourcefile~field.f90 sourcefile~turbine_dummy.f90->sourcefile~turbine_model.f90 sourcefile~turbine_model.f90->sourcefile~backend.f90~3 sourcefile~turbine_model.f90->sourcefile~common.f90~3 sourcefile~turbine_model.f90->sourcefile~mesh.f90 sourcefile~turbine_model.f90->sourcefile~allocator.f90~2 sourcefile~turbine_model.f90->sourcefile~checkpoint_state.f90 sourcefile~turbine_model.f90->sourcefile~field.f90

Source Code

module m_logger
  !! Single point for x3d2 to report progress, warnings and errors, and to
  !! stop the run when something goes wrong.
  !!
  !! Messages carry a level: debug, info, warning or error. Those below the
  !! threshold set with `set_log_level` (info by default) are dropped. Debug
  !! and info lines go to standard output, warnings and errors to standard
  !! error, and every line is flushed so output from different ranks and
  !! from a crash is not lost in a buffer.
  !!
  !! The logging calls are made on every rank, but by default only rank 0
  !! writes, so a message appears once however many ranks the run has. Pass
  !! `all_ranks=.true.` for something that only some ranks know about; each
  !! rank that makes the call then writes, and on a multi-rank run the line
  !! starts with the rank that wrote it.
  !!
  !! `abort_run` is how x3d2 stops on an error. It writes the message and
  !! takes down the whole job: a plain `error stop` on one rank can leave the
  !! others waiting forever in MPI. `check_mpi` turns an MPI return code into
  !! such an abort. Backends add their own checks on top of `abort_run` (see
  !! m_cuda_errors for CUDA).
  !!
  !! `str` turns numbers into text, so a message can be assembled with `//`:
  !!
  !!   call log_info('Checkpoint frequency: '//str(freq))
  use iso_fortran_env, only: int32, int64, real32, real64, &
                             stdout => output_unit, stderr => error_unit

  use m_mpi, only: MPI_COMM_WORLD, MPI_SUCCESS, MPI_MAX_ERROR_STRING, &
                   MPI_Initialized, MPI_Finalized, MPI_Comm_rank, &
                   MPI_Comm_size, MPI_Barrier, MPI_Abort, MPI_Error_string

  implicit none

  private
  public :: LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARN, LOG_LEVEL_ERROR
  public :: set_log_level, get_log_level
  public :: log_debug, log_info, log_warn, log_error
  public :: abort_run, check_mpi
  public :: str

  integer, parameter :: LOG_LEVEL_DEBUG = 10
  integer, parameter :: LOG_LEVEL_INFO = 20
  integer, parameter :: LOG_LEVEL_WARN = 30
  integer, parameter :: LOG_LEVEL_ERROR = 40

  integer :: log_level = LOG_LEVEL_INFO

  !> Exit code of a run stopped by abort_run.
  integer, parameter :: abort_code = 1

  !> Default edit descriptors `str` uses for reals: enough significant digits
  !> (9 and 17) that no value loses precision when printed.
  character(len=*), parameter :: real32_fmt = '(es15.8)'
  character(len=*), parameter :: real64_fmt = '(es24.16e3)'

  interface str
    module procedure str_int32
    module procedure str_int64
    module procedure str_real32
    module procedure str_real64
    module procedure str_logical
  end interface str

contains

  subroutine set_log_level(level)
    !! Drop messages below `level` (one of the LOG_LEVEL_* parameters).
    integer, intent(in) :: level

    log_level = level
  end subroutine set_log_level

  integer function get_log_level()
    get_log_level = log_level
  end function get_log_level

  subroutine log_debug(message, all_ranks)
    !! Detail for developers, hidden unless the level is LOG_LEVEL_DEBUG.
    character(len=*), intent(in) :: message
    logical, intent(in), optional :: all_ranks

    call write_message(LOG_LEVEL_DEBUG, 'DEBUG: ', message, all_ranks)
  end subroutine log_debug

  subroutine log_info(message, all_ranks)
    !! Progress and setup information.
    character(len=*), intent(in) :: message
    logical, intent(in), optional :: all_ranks

    call write_message(LOG_LEVEL_INFO, '', message, all_ranks)
  end subroutine log_info

  subroutine log_warn(message, all_ranks)
    !! Something is suspicious, but the run can carry on.
    character(len=*), intent(in) :: message
    logical, intent(in), optional :: all_ranks

    call write_message(LOG_LEVEL_WARN, 'WARNING: ', message, all_ranks)
  end subroutine log_warn

  subroutine log_error(message, all_ranks)
    !! An error the caller handles itself. Use abort_run to stop the run.
    character(len=*), intent(in) :: message
    logical, intent(in), optional :: all_ranks

    call write_message(LOG_LEVEL_ERROR, 'ERROR: ', message, all_ranks)
  end subroutine log_error

  subroutine abort_run(message, collective)
    !! Report a fatal error and stop every rank of the run.
    !!
    !! By default the rank that calls this writes the message, prefixed with
    !! its rank on a multi-rank run, and aborts the job. That is safe however
    !! many ranks get here, so it is the right choice for a failure only some
    !! ranks see: a CUDA error, a missing file, a bad MPI return code.
    !!
    !! Pass `collective=.true.` when every rank is certain to reach this call
    !! with the same message, typically while checking the input. Rank 0 then
    !! writes the message once and aborts, while the other ranks wait for it.
    !! Never use it for an error some ranks may not see: those ranks would
    !! carry on while the rest wait, and the run hangs.
    character(len=*), intent(in) :: message
    logical, intent(in), optional :: collective

    logical :: is_collective, mpi_running
    integer :: rank, nproc, ierr

    is_collective = .false.
    if (present(collective)) is_collective = collective

    call query_mpi(mpi_running, rank, nproc)

    if (is_collective .and. rank /= 0) then
      ! Rank 0 is reporting this same error and will abort the job. Waiting
      ! here, rather than aborting too, keeps this rank from killing the job
      ! before rank 0 has written the message. The barrier never completes
      ! because rank 0 does not join it.
      call MPI_Barrier(MPI_COMM_WORLD, ierr)
    end if

    call emit(stderr, line_prefix(.not. is_collective, rank, nproc) &
              //'ERROR: '//message)

    if (mpi_running .and. nproc > 1) then
      call MPI_Abort(MPI_COMM_WORLD, abort_code, ierr)
    end if
    ! A single rank, or MPI not running: stop this process.
    error stop abort_code
  end subroutine abort_run

  subroutine check_mpi(ierr, operation)
    !! Abort the run if an MPI call did not succeed.
    !!
    !! `operation` says what was being done, for example 'MPI_Waitall in
    !! sendrecv_fields', and appears in the message with MPI's own
    !! description of the error.
    integer, intent(in) :: ierr
    character(len=*), intent(in) :: operation

    character(len=MPI_MAX_ERROR_STRING) :: description
    integer :: description_len, ierr_string

    if (ierr == MPI_SUCCESS) return

    call MPI_Error_string(ierr, description, description_len, ierr_string)
    if (ierr_string /= MPI_SUCCESS) then
      description = 'unknown error'
      description_len = len_trim(description)
    end if
    call abort_run(operation//' failed: '//description(1:description_len) &
                   //' (MPI error code '//str(ierr)//')')
  end subroutine check_mpi

  subroutine write_message(level, tag, message, all_ranks)
    integer, intent(in) :: level
    character(len=*), intent(in) :: tag, message
    logical, intent(in), optional :: all_ranks

    logical :: every_rank, mpi_running
    integer :: rank, nproc, unit

    if (level < log_level) return

    every_rank = .false.
    if (present(all_ranks)) every_rank = all_ranks

    call query_mpi(mpi_running, rank, nproc)
    if (.not. every_rank .and. rank /= 0) return

    unit = stdout
    if (level >= LOG_LEVEL_WARN) unit = stderr
    call emit(unit, line_prefix(every_rank, rank, nproc)//tag//message)
  end subroutine write_message

  subroutine query_mpi(mpi_running, rank, nproc)
    !! Rank and size of MPI_COMM_WORLD, which can only be asked between
    !! MPI_Init and MPI_Finalize. Outside that window this process counts as
    !! a single rank 0.
    logical, intent(out) :: mpi_running
    integer, intent(out) :: rank, nproc

    logical :: initialised, finalised
    integer :: ierr

    rank = 0
    nproc = 1
    call MPI_Initialized(initialised, ierr)
    call MPI_Finalized(finalised, ierr)
    mpi_running = initialised .and. .not. finalised
    if (mpi_running) then
      call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
      call MPI_Comm_size(MPI_COMM_WORLD, nproc, ierr)
    end if
  end subroutine query_mpi

  function line_prefix(show_rank, rank, nproc) result(prefix)
    !! Names the writing rank, when there is more than one to tell apart.
    logical, intent(in) :: show_rank
    integer, intent(in) :: rank, nproc
    character(len=:), allocatable :: prefix

    if (show_rank .and. nproc > 1) then
      prefix = '[rank '//str(rank)//'] '
    else
      prefix = ''
    end if
  end function line_prefix

  subroutine emit(unit, line)
    integer, intent(in) :: unit
    character(len=*), intent(in) :: line

    write (unit, '(a)') line
    flush (unit)
  end subroutine emit

  function str_int32(value) result(text)
    integer(int32), intent(in) :: value
    character(len=:), allocatable :: text

    character(len=11) :: buffer

    write (buffer, '(i0)') value
    text = trim(buffer)
  end function str_int32

  function str_int64(value) result(text)
    integer(int64), intent(in) :: value
    character(len=:), allocatable :: text

    character(len=20) :: buffer

    write (buffer, '(i0)') value
    text = trim(buffer)
  end function str_int64

  function str_real32(value, fmt) result(text)
    !! `fmt` is a format string such as '(f8.3)'; the default is scientific
    !! notation with nine significant digits.
    real(real32), intent(in) :: value
    character(len=*), intent(in), optional :: fmt
    character(len=:), allocatable :: text

    character(len=64) :: buffer

    if (present(fmt)) then
      write (buffer, fmt) value
    else
      write (buffer, real32_fmt) value
    end if
    text = trim(adjustl(buffer))
  end function str_real32

  function str_real64(value, fmt) result(text)
    !! `fmt` is a format string such as '(f8.3)'; the default is scientific
    !! notation with seventeen significant digits.
    real(real64), intent(in) :: value
    character(len=*), intent(in), optional :: fmt
    character(len=:), allocatable :: text

    character(len=64) :: buffer

    if (present(fmt)) then
      write (buffer, fmt) value
    else
      write (buffer, real64_fmt) value
    end if
    text = trim(adjustl(buffer))
  end function str_real64

  function str_logical(value) result(text)
    logical, intent(in) :: value
    character(len=:), allocatable :: text

    text = merge('T', 'F', value)
  end function str_logical

end module m_logger