Program Listing for File checkNan.cpp

Return to documentation for file (dataBlock/checkNan.cpp)

// ***********************************************************************************
// Idefix MHD astrophysical code
// Copyright(C) 2020-2022 Geoffroy R. J. Lesur <geoffroy.lesur@univ-grenoble-alpes.fr>
// and other code contributors
// Licensed under CeCILL 2.1 License, see COPYING for more information
// ***********************************************************************************

#include "dataBlock.hpp"
#include "dataBlockHost.hpp"

// Check if current datablock has nans

int DataBlock::CheckNan()  {
  int nanVs=0;
  int nanVc=0;

  idfx::pushRegion("DataBlock::CheckNan");
  IdefixArray4D<real> Vc=this->hydro.Vc;

  idefix_reduce("checkNanVc",
    0, NVAR,
    beg[KDIR], end[KDIR],
    beg[JDIR], end[JDIR],
    beg[IDIR], end[IDIR],
    KOKKOS_LAMBDA (int n, int k, int j, int i, int &nnan) {
      if(std::isnan(Vc(n,k,j,i))) nnan++;
    }, Kokkos::Sum<int>(nanVc) // reduction variable
  );

  #if MHD == YES
    IdefixArray4D<real> Vs=this->hydro.Vs;
    idefix_reduce("checkNanVs",
      0, DIMENSIONS,
      beg[KDIR], end[KDIR]+KOFFSET,
      beg[JDIR], end[JDIR]+JOFFSET,
      beg[IDIR], end[IDIR]+IOFFSET,
      KOKKOS_LAMBDA (int n, int k, int j, int i, int &nnan) {
        if(std::isnan(Vs(n,k,j,i))) nnan++;
      }, Kokkos::Sum<int>(nanVs) // reduction variable
    );
  #endif

  int nanTot = nanVc+nanVs;
  #ifdef WITH_MPI
    MPI_Allreduce(MPI_IN_PLACE, &nanTot,1,MPI_INT, MPI_SUM, MPI_COMM_WORLD);
  #endif
  if(nanTot>0) {
    idfx::cout << "DataBlock: Nans were found in the current calculation" << std::endl;
    if(nanVc+nanVs>0) {
      // Each datablock shows its findings to stdout
      std::cout << "DataBlock: rank " << idfx::prank << " found " << nanVc << " Nans in Vc"
      #if MHD == YES
        << " and " << nanVs << " Nans in Vs"
      #endif
        << " in the current datablock. Details will be in corresponding process log file."
        << std::endl;

      // We need to make copies to find exactly where the thing is wrong
      DataBlockHost dataHost(*this);
      dataHost.SyncFromDevice();

      int nerrormax=10;

      for(int k = beg[KDIR] ; k < end[KDIR] ; k++) {
        for(int j = beg[JDIR] ; j < end[JDIR] ; j++) {
          for(int i = beg[IDIR] ; i < end[IDIR] ; i++) {
            for(int n = 0 ; n < NVAR ; n ++) {
              if(std::isnan(dataHost.Vc(n,k,j,i)) && nerrormax>0) {
                nerrormax--;
                idfx::cout << "rank " << idfx::prank << ": Nan found  in variable "
                  << this->hydro.VcName[n] << std::endl;

                idfx::cout << "      global (i,j,k) = (" << i-beg[IDIR]+gbeg[IDIR]-nghost[IDIR]
                  << ", " << j-beg[JDIR]+gbeg[JDIR]-nghost[JDIR] << ", "
                  << k-beg[KDIR]+gbeg[KDIR]-nghost[KDIR] << ")" << std::endl;

                idfx::cout << "      global (x,y,z) = (" << dataHost.x[IDIR](i) << ", "
                  <<  dataHost.x[JDIR](j) << ", " << dataHost.x[KDIR](k) << ")" << std::endl;
              }
            }
          }
        }
      }

  #if MHD == YES
      for(int k = beg[KDIR] ; k < end[KDIR]+KOFFSET ; k++) {
        for(int j = beg[JDIR] ; j < end[JDIR]+JOFFSET ; j++) {
          for(int i = beg[IDIR] ; i < end[IDIR]+IOFFSET ; i++) {
            for(int n = 0 ; n < DIMENSIONS ; n ++) {
              if(std::isnan(dataHost.Vs(n,k,j,i)) && nerrormax>0) {
                nerrormax--;
                idfx::cout << "rank " << idfx::prank << ": Nan found  in variable "
                  << this->hydro.VsName[n] << std::endl;
                idfx::cout << "      global (i,j,k) = (" << i-beg[IDIR]+gbeg[IDIR]-nghost[IDIR]
                  << ", " << j-beg[JDIR]+gbeg[JDIR]-nghost[JDIR] << ", "
                  << k-beg[KDIR]+gbeg[KDIR]-nghost[KDIR] << ")" << std::endl;

                idfx::cout << "      global (x,y,z) = (" << dataHost.x[IDIR](i) << ", "
                  <<  dataHost.x[JDIR](j) << ", " << dataHost.x[KDIR](k) << ")" << std::endl;
              }
            }
          }
        }
      }
  #endif
      if(nerrormax<=0) {
        idfx::cout << "... " << std::endl << "*** More Nans have been found in current dataBlock. "
          << "Only showing the first 10." << std::endl;
      }
    }
  }
  idfx::popRegion();
  return(nanTot);
}