807 dccrg::Dccrg<SpatialCell, dccrg::Cartesian_Geometry>& mpiGrid) {
808 phiprof::Timer fluxTracingTimer {
"fieldtracing-fullAndFluxTracing"};
811 int localDccrgSize = localDccrgCells.size();
813 MPI_Allreduce(&localDccrgSize, &globalDccrgSize, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
815 MPI_Comm_size(MPI_COMM_WORLD, &commSize);
816 std::vector<int> amounts(commSize);
817 std::vector<int> displacements(commSize);
818 std::vector<CellID> allDccrgCells(globalDccrgSize);
819 MPI_Allgather(&localDccrgSize, 1, MPI_INT, amounts.data(), 1, MPI_INT, MPI_COMM_WORLD);
820 for (
int i = 1;
i < commSize;
i++) {
821 displacements[
i] = displacements[
i - 1] + amounts[
i - 1];
823 MPI_Allgatherv(localDccrgCells.data(), localDccrgSize, MPI_UINT64_T, allDccrgCells.data(), amounts.data(), displacements.data(), MPI_UINT64_T, MPI_COMM_WORLD);
826 const TReal stepSize =
min(1000e3,
fsgrid.getGridSpacing()[0] / 2.);
827 std::vector<TReal> cellFWTracingStepSize(globalDccrgSize, stepSize);
828 std::vector<TReal> cellBWTracingStepSize(globalDccrgSize, stepSize);
830 std::array<fsgrid::FsSize_t, 3> gridSize =
fsgrid.getGlobalSize();
835 gridSize[0]*
fsgrid.getGridSpacing()[0] + gridSize[1]*
fsgrid.getGridSpacing()[1] + gridSize[2]*
fsgrid.getGridSpacing()[2];
837 std::vector<TReal> cellCurvatureRadius(globalDccrgSize);
838 std::vector<TReal> reducedCellCurvatureRadius(globalDccrgSize);
843 std::vector<std::array<TReal, 3>> cellFWTracingCoordinates(globalDccrgSize);
844 std::vector<std::array<TReal, 3>> cellBWTracingCoordinates(globalDccrgSize);
845 std::vector<TReal> cellFWRunningDistance(globalDccrgSize);
846 std::vector<TReal> cellBWRunningDistance(globalDccrgSize);
849 std::vector<TReal> cellMaxExtension(globalDccrgSize);
852 std::vector<std::array<TReal, 3>> sumCellFWTracingCoordinates(globalDccrgSize);
853 std::vector<std::array<TReal, 3>> sumCellBWTracingCoordinates(globalDccrgSize);
854 std::vector<TReal> reducedCellFWRunningDistance(globalDccrgSize);
855 std::vector<TReal> reducedCellBWRunningDistance(globalDccrgSize);
856 std::vector<TReal> reducedCellFWTracingStepSize(globalDccrgSize);
857 std::vector<TReal> reducedCellBWTracingStepSize(globalDccrgSize);
858 std::vector<signed char> storedCellFWConnection(globalDccrgSize);
859 std::vector<signed char> storedCellBWConnection(globalDccrgSize);
861 phiprof::Timer initializationTimer {
"initialization-loop"};
862 for (
int n = 0; n < globalDccrgSize; n++) {
863 const CellID id = allDccrgCells[n];
864 const std::array<Real, 3> ctr = mpiGrid.get_center(
id);
865 cellFWTracingCoordinates.at(n) = {(
TReal)ctr[0], (
TReal)ctr[1], (
TReal)ctr[2]};
866 cellBWTracingCoordinates.at(n) = cellFWTracingCoordinates.at(n);
867 if (mpiGrid.is_local(
id)) {
878 cellFWTracingCoordinates[n] = {0,0,0};
879 cellBWTracingCoordinates[n] = {0,0,0};
880 cellFWTracingStepSize[n] = 0;
881 cellBWTracingStepSize[n] = 0;
884 if (
fieldTracingParameters.fluxrope_max_curvature_radii_to_trace * cellCurvatureRadius[n] > maxTracingDistance) {
885 cellCurvatureRadius[n] = 0;
890 initializationTimer.stop();
894 const std::vector<std::array<TReal,3>> cellInitialCoordinates = cellFWTracingCoordinates;
897 MPI_Allreduce(cellFWConnection.data(), storedCellFWConnection.data(), globalDccrgSize, MPI_SIGNED_CHAR, MPI_MAX, MPI_COMM_WORLD);
898 MPI_Allreduce(cellBWConnection.data(), storedCellBWConnection.data(), globalDccrgSize, MPI_SIGNED_CHAR, MPI_MAX, MPI_COMM_WORLD);
899 if (
sizeof(
TReal) ==
sizeof(
double)) {
900 MPI_Allreduce(cellFWTracingStepSize.data(), reducedCellFWTracingStepSize.data(), globalDccrgSize, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
901 MPI_Allreduce(cellBWTracingStepSize.data(), reducedCellBWTracingStepSize.data(), globalDccrgSize, MPI_DOUBLE, MPI_MIN, MPI_COMM_WORLD);
902 MPI_Allreduce(cellCurvatureRadius.data(), reducedCellCurvatureRadius.data(), globalDccrgSize, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
904 MPI_Allreduce(cellFWTracingStepSize.data(), reducedCellFWTracingStepSize.data(), globalDccrgSize, MPI_FLOAT, MPI_MIN, MPI_COMM_WORLD);
905 MPI_Allreduce(cellBWTracingStepSize.data(), reducedCellBWTracingStepSize.data(), globalDccrgSize, MPI_FLOAT, MPI_MIN, MPI_COMM_WORLD);
906 MPI_Allreduce(cellCurvatureRadius.data(), reducedCellCurvatureRadius.data(), globalDccrgSize, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
909 cellFWConnection = storedCellFWConnection;
910 cellBWConnection = storedCellBWConnection;
911 cellFWTracingStepSize.swap(reducedCellFWTracingStepSize);
912 cellBWTracingStepSize.swap(reducedCellBWTracingStepSize);
913 cellCurvatureRadius.swap(reducedCellCurvatureRadius);
915 TracingFieldFunction<TReal> tracingFullField = [&perb, &dperb, &technical, &
fsgrid](std::array<TReal, 3>& r,
const bool alongB, std::array<TReal, 3>& b) ->
bool {
919 bool warnMaxDistanceExceeded =
false;
920 int cellsToDoFullBox, cellsToDoFluxRopes;
921 int smallSizeFW, smallSizeBW;
923 std::vector<int> indicesToReduceFW, indicesToReduceBW;
924 std::vector<std::array<TReal, 3>> smallCellFWTracingCoordinates, smallCellBWTracingCoordinates;
925 std::vector<TReal> smallCellFWRunningDistance, smallCellBWRunningDistance;
926 std::vector<TReal> smallCellFWTracingStepSize, smallCellBWTracingStepSize;
927 std::vector<signed char> smallCellFWConnection, smallCellBWConnection;
929 std::vector<std::array<TReal, 3>> smallSumCellFWTracingCoordinates, smallSumCellBWTracingCoordinates;
930 std::vector<TReal> smallReducedCellFWRunningDistance, smallReducedCellBWRunningDistance;
931 std::vector<TReal> smallReducedCellFWTracingStepSize, smallReducedCellBWTracingStepSize;
932 std::vector<signed char> smallReducedCellFWConnection, smallReducedCellBWConnection;
934 int mpi_timer{phiprof::initializeTimer(
"MPI-loop")};
935 phiprof::Timer loopTimer{
"loop"};
936 #pragma omp parallel shared(cellsToDoFullBox, cellsToDoFluxRopes)
946 #pragma omp for schedule(dynamic)
947 for (
int n = 0; n < globalDccrgSize; n++) {
950 cellFWTracingCoordinates, cellFWTracingStepSize, cellFWRunningDistance,
951 cellMaxExtension, cellFWConnection, warnMaxDistanceExceeded, maxTracingDistance,
956 cellBWTracingCoordinates, cellBWTracingStepSize, cellBWRunningDistance,
957 cellMaxExtension, cellBWConnection, warnMaxDistanceExceeded, maxTracingDistance,
963 phiprof::Timer timer{mpi_timer};
966 indicesToReduceFW.clear();
967 indicesToReduceBW.clear();
968 smallCellFWTracingCoordinates.clear();
969 smallCellBWTracingCoordinates.clear();
970 smallCellFWRunningDistance.clear();
971 smallCellBWRunningDistance.clear();
972 smallCellFWTracingStepSize.clear();
973 smallCellBWTracingStepSize.clear();
974 smallCellFWConnection.clear();
975 smallCellBWConnection.clear();
976 for (
int n = 0; n < globalDccrgSize; n++) {
980 indicesToReduceFW.push_back(n);
981 smallCellFWTracingCoordinates.push_back(cellFWTracingCoordinates[n]);
982 smallCellFWRunningDistance.push_back(cellFWRunningDistance[n]);
983 smallCellFWTracingStepSize.push_back(cellFWTracingStepSize[n]);
984 smallCellFWConnection.push_back(cellFWConnection[n]);
989 indicesToReduceBW.push_back(n);
990 smallCellBWTracingCoordinates.push_back(cellBWTracingCoordinates[n]);
991 smallCellBWRunningDistance.push_back(cellBWRunningDistance[n]);
992 smallCellBWTracingStepSize.push_back(cellBWTracingStepSize[n]);
993 smallCellBWConnection.push_back(cellBWConnection[n]);
996 smallSizeFW = indicesToReduceFW.size();
997 smallSizeBW = indicesToReduceBW.size();
999 smallSumCellFWTracingCoordinates.resize(smallSizeFW);
1000 smallSumCellBWTracingCoordinates.resize(smallSizeBW);
1001 smallReducedCellFWRunningDistance.resize(smallSizeFW);
1002 smallReducedCellBWRunningDistance.resize(smallSizeBW);
1003 smallReducedCellFWTracingStepSize.resize(smallSizeFW);
1004 smallReducedCellBWTracingStepSize.resize(smallSizeBW);
1005 smallReducedCellFWConnection.resize(smallSizeFW);
1006 smallReducedCellBWConnection.resize(smallSizeBW);
1008 MPI_Allreduce(smallCellFWConnection.data(), smallReducedCellFWConnection.data(), smallSizeFW, MPI_SIGNED_CHAR, MPI_MAX, MPI_COMM_WORLD);
1009 MPI_Allreduce(smallCellBWConnection.data(), smallReducedCellBWConnection.data(), smallSizeBW, MPI_SIGNED_CHAR, MPI_MAX, MPI_COMM_WORLD);
1010 if (
sizeof(
TReal) ==
sizeof(
double)) {
1011 MPI_Allreduce(smallCellFWTracingCoordinates.data(), smallSumCellFWTracingCoordinates.data(), 3*smallSizeFW, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1012 MPI_Allreduce(smallCellBWTracingCoordinates.data(), smallSumCellBWTracingCoordinates.data(), 3*smallSizeBW, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
1013 MPI_Allreduce(smallCellFWTracingStepSize.data(), smallReducedCellFWTracingStepSize.data(), smallSizeFW, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
1014 MPI_Allreduce(smallCellBWTracingStepSize.data(), smallReducedCellBWTracingStepSize.data(), smallSizeBW, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
1015 MPI_Allreduce(smallCellFWRunningDistance.data(), smallReducedCellFWRunningDistance.data(), smallSizeFW, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
1016 MPI_Allreduce(smallCellBWRunningDistance.data(), smallReducedCellBWRunningDistance.data(), smallSizeBW, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
1018 MPI_Allreduce(smallCellFWTracingCoordinates.data(), smallSumCellFWTracingCoordinates.data(), 3*smallSizeFW, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD);
1019 MPI_Allreduce(smallCellBWTracingCoordinates.data(), smallSumCellBWTracingCoordinates.data(), 3*smallSizeBW, MPI_FLOAT, MPI_SUM, MPI_COMM_WORLD);
1020 MPI_Allreduce(smallCellFWTracingStepSize.data(), smallReducedCellFWTracingStepSize.data(), smallSizeFW, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
1021 MPI_Allreduce(smallCellBWTracingStepSize.data(), smallReducedCellBWTracingStepSize.data(), smallSizeBW, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
1022 MPI_Allreduce(smallCellFWRunningDistance.data(), smallReducedCellFWRunningDistance.data(), smallSizeFW, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
1023 MPI_Allreduce(smallCellBWRunningDistance.data(), smallReducedCellBWRunningDistance.data(), smallSizeBW, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
1027 #pragma omp for schedule(dynamic)
1028 for (
int n = 0; n < smallSizeFW; n++) {
1029 cellFWTracingStepSize[indicesToReduceFW[n]] = smallReducedCellFWTracingStepSize[n];
1030 cellFWRunningDistance[indicesToReduceFW[n]] = smallReducedCellFWRunningDistance[n];
1031 cellFWConnection[indicesToReduceFW[n]] = smallReducedCellFWConnection[n];
1032 cellFWTracingCoordinates[indicesToReduceFW[n]] = smallSumCellFWTracingCoordinates[n];
1034 #pragma omp for schedule(dynamic)
1035 for (
int n = 0; n < smallSizeBW; n++) {
1036 cellBWTracingStepSize[indicesToReduceBW[n]] = smallReducedCellBWTracingStepSize[n];
1037 cellBWRunningDistance[indicesToReduceBW[n]] = smallReducedCellBWRunningDistance[n];
1038 cellBWConnection[indicesToReduceBW[n]] = smallReducedCellBWConnection[n];
1039 cellBWTracingCoordinates[indicesToReduceBW[n]] = smallSumCellBWTracingCoordinates[n];
1044 cellsToDoFullBox = 0;
1045 cellsToDoFluxRopes = 0;
1047 storedCellFWConnection = cellFWConnection;
1048 storedCellBWConnection = cellBWConnection;
1050 #pragma omp for schedule(dynamic) reduction(+ : cellsToDoFullBox) reduction(+ : cellsToDoFluxRopes)
1051 for (
int n = 0; n < globalDccrgSize; n++) {
1057 cellsToDoFluxRopes++;
1067 logFile <<
"(fieldtracing) combined flux rope + full box tracing traced in " << itCount
1068 <<
" iterations of the tracing loop with flux rope " << cellsToDoFluxRopes <<
", full box "
1069 << cellsToDoFullBox <<
" remaining incomplete field lines (total spatial cells " << globalDccrgSize <<
")."
1072 bool redWarning =
false;
1073 MPI_Allreduce(&warnMaxDistanceExceeded, &redWarning, 1, MPI_C_BOOL, MPI_LOR, MPI_COMM_WORLD);
1075 MPI_Comm_rank(MPI_COMM_WORLD, &rank);
1077 logFile <<
"(fieldtracing) Warning: reached the maximum tracing distance " << maxTracingDistance
1078 <<
" m allowed for combined flux rope + full box tracing." << endl;
1082 std::vector<TReal> reducedCellMaxExtension(globalDccrgSize);
1083 if (
sizeof(
TReal) ==
sizeof(
double)) {
1084 MPI_Allreduce(cellMaxExtension.data(), reducedCellMaxExtension.data(), globalDccrgSize, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
1086 MPI_Allreduce(cellMaxExtension.data(), reducedCellMaxExtension.data(), globalDccrgSize, MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD);
1089 phiprof::Timer finalLoopTimer {
"final-loop"};
1090 for (
int n = 0; n < globalDccrgSize; n++) {
1091 const CellID id = allDccrgCells.at(n);
1092 if (mpiGrid.is_local(
id)) {
1100 mpiGrid[id]->parameters[
CellParams::FLUXROPE] = reducedCellMaxExtension[n] / cellCurvatureRadius[n];
1144 finalLoopTimer.stop();