Exemple #1
0
int check_convergence_dprimme(double *V, double *W, double *hVecs, 
   double *hVals, int *flags, int basisSize, int *iev, int *ievMax, 
   double *blockNorms, int *blockSize, int numConverged, int numLocked, 
   double *evecs, double tol, double maxConvTol, double aNormEstimate, 
   double *rwork, primme_params *primme) {

   int i;             /* Loop variable                                        */
   int left, right;   /* Range of block vectors to be checked for convergence */
   int start;         /* starting index in block of converged/tobeProject vecs*/
   int numVacancies;  /* Number of vacant positions between left and right    */
   int recentlyConverged; /* The number of Ritz values declared converged     */
                          /* since the last iteration                         */
   int numToProject;      /* Number of vectors with potential accuracy problem*/
   double attainableTol;  /* Used in locking to check near convergence problem*/

   /* -------------------------------------------- */
   /* Tolerance based on our dynamic norm estimate */
   /* -------------------------------------------- */

   if (primme->aNorm <= 0.0L) {
      tol = tol * aNormEstimate;
   }

   /* ---------------------------------------------------------------------- */
   /* If locking, set tol beyond which we need to check for accuracy problem */
   /* ---------------------------------------------------------------------- */
   if (primme->locking) {
      attainableTol = sqrt(primme->numOrthoConst+numLocked)*maxConvTol;
   }   

      
   /* --------------------------------------------------------------- */
   /* Compute each Ritz vector and its corresponding residual vector. */
   /* The Ritz vector and residual are stored temporarily in V and W  */
   /* respectively.  For each Ritz vector, determine if it has        */
   /* converged.  If it has, try to replace it with one that hasn't.  */
   /* --------------------------------------------------------------- */

   recentlyConverged = 0;
   left = 0;
   right = *blockSize - 1;
   numVacancies = 1;

   while (numVacancies > 0 && 
          (numConverged + recentlyConverged) < primme->numEvals) {

      /* Consider the newly added vectors in the block and reset counters */
      numVacancies = 0;
      numToProject = 0;

      /* Copy needed hvecs into the front of the work array. */

      for (i=left; i <= right; i++) {
         Num_dcopy_dprimme(basisSize, &hVecs[basisSize*iev[i]], 1, 
            &rwork[basisSize*(i-left)], 1);
      }
            
      /* ----------------------------------------------------------------- */
      /* Compute the Ritz vectors, residuals, and norms for the next       */
      /* blockSize unconverged Ritz vectors.  The Ritz vectors will be     */
      /* placed from V(0,lft) to V(0,rgt) and the residual vectors from    */
      /* W(0,lft) to W(0,rgt).                                             */
      /* ----------------------------------------------------------------- */
      /* rwork must be maxBasisSize*maxBlockSize + maxBlockSize in size,   */
      /* maxBasisSize*maxBlockSize holds selected hVecs to facilitate      */
      /* blocking, and maxBlockSize to hold the residual norms             */
      /* ----------------------------------------------------------------- */

      compute_resnorms(V, W, rwork, hVals, basisSize, blockNorms,
         iev, left, right, &rwork[basisSize*(right-left+1)], primme);

      print_residuals(hVals, blockNorms, numConverged, numLocked, iev, 
         left, right, primme);

      /* ----------------------------------------------------------------- */
      /* Determine which Ritz vectors have converged < tol and flag them.  */
      /* ----------------------------------------------------------------- */

      for (i=left; i <= right; i++) {
       
         /* ------------------------------------*/
         /* If the vector is converged, flag it */
         /* ------------------------------------*/
         if (blockNorms[i] < tol) {
            flags[iev[i]] = CONVERGED;
            numVacancies++;

            if ((!primme->locking && iev[i] < primme->numEvals) || 
               (primme->locking && ((numLocked + iev[i]) < primme->numEvals))) {

               recentlyConverged++;

               if (!primme->locking && primme->procID == 0 && 
                   primme->printLevel >= 2) { fprintf(primme->outputFile, 
                  "#Converged %d eval[ %d ]= %e norm %e Mvecs %d Time %g\n",
                  numConverged+recentlyConverged, iev[i], hVals[iev[i]], 
                  blockNorms[i], primme->stats.numMatvecs,primme_wTimer(0));
                  fflush(primme->outputFile);
               } /* printf */
            } /*if */
         } /*if converged */
         /* ---------------------------------------------------------------- */
         /* If locking there may be an accuracy problem close to convergence */
         /* Check if there is danger and set these Ritz vecs for projection  */
         /* ---------------------------------------------------------------- */
         else if (primme->locking && numLocked > 0 &&
                  blockNorms[i] < attainableTol ) {

            flags[iev[i]] = TO_BE_PROJECTED;
            numToProject++;
         }

      } /* for */

      /* ---------------------------------------------------------------- */
      /* If some of the Ritz vectors in the block have converged, or need */
      /* to be projected against evecs, move those flagged Ritz vectors   */
      /* and residuals towards the end of the block [left,right]. Also    */
      /* swap iev, and blockNorms for the targeted block.                 */
      /* ---------------------------------------------------------------- */
      if (numVacancies > 0 || numToProject > 0) {

         swap_UnconvVecs(V, W, primme->nLocal, basisSize, iev, flags, 
            blockNorms, primme->numOrthoConst + numLocked, *blockSize, left);
      }
      /* --------------------------------------------------------------- */
      /* Project the TO_BE_PROJECTED residuals and check for practical   */
      /* convergence among them. Those practically converged evecs are   */
      /* swapped just before the converged ones at the end of the block. */
      /* numVacancies and recentlyConverged are also updated             */
      /* --------------------------------------------------------------- */
      if (numToProject > 0) {

         start = *blockSize - numVacancies - numToProject;

         check_practical_convergence(V, W, evecs, numLocked, basisSize, 
            *blockSize, start, numToProject, iev, flags, blockNorms, tol, 
            &recentlyConverged, &numVacancies, rwork, primme);
      }

      /* ---------------------------------------------------------------- */
      /* Replace the vacancies, with as many unconverged vectors beyond   */
      /* ievMax as possible. If not enough are available reduce blockSize */
      /* ---------------------------------------------------------------- */

      if (numVacancies > 0) {
         replace_vectors(iev, flags, *blockSize, basisSize, numVacancies, 
                         &left, &right, ievMax); 
         numVacancies = right - left + 1;
         *blockSize = left + numVacancies;
      }

   } /* while there are vacancies */

   return recentlyConverged;
}
Exemple #2
0
int
main(int argc, char *argv[])
{
  size_t nmax_int = 60;
  size_t mmax_int = 6;
  size_t nmax_ext = 0;
  size_t mmax_ext = 0;
  size_t nmax_sh = 60;
  size_t mmax_sh = 5;
  size_t nmax_tor = 60;
  size_t mmax_tor = 5;
  double alpha_int = 1.0;
  double alpha_sh = 1.0;
  double alpha_tor = 1.0;
  size_t robust_maxit = 5;
  const double R = R_EARTH_KM;
  const double b = R + 110.0;   /* radius of internal current shell (Sq+EEJ) */
  const double d = R + 350.0;   /* radius of current shell for gravity/diamag */
  double universal_time = 11.0; /* UT in hours for data selection */
  char *datamap_file = "datamap.dat";
  char *data_file = "data.dat";
  char *spectrum_file = "poltor.s";
  char *corr_file = "corr.dat";
  char *residual_file = NULL;
  char *output_file = NULL;
  char *chisq_file = NULL;
  char *lls_file = NULL;
  char *Lcurve_file = NULL;
  magdata *mdata = NULL;
  poltor_workspace *poltor_p;
  poltor_parameters params;
  struct timeval tv0, tv1;
  int print_data = 0;

#if POLTOR_SYNTH_DATA
  nmax_int = 30;
  mmax_int = 10;
  nmax_ext = 2;
  mmax_ext = 2;
  nmax_sh = 20;
  mmax_sh = 10;
  nmax_tor = 30;
  mmax_tor = 10;
#endif

  while (1)
    {
      int c;
      int option_index = 0;
      static struct option long_options[] =
        {
          { "nmax_int", required_argument, NULL, 'n' },
          { "mmax_int", required_argument, NULL, 'm' },
          { "nmax_tor", required_argument, NULL, 'a' },
          { "mmax_tor", required_argument, NULL, 'b' },
          { "nmax_sh", required_argument, NULL, 'e' },
          { "mmax_sh", required_argument, NULL, 'f' },
          { "nmax_ext", required_argument, NULL, 'g' },
          { "mmax_ext", required_argument, NULL, 'h' },
          { "residual_file", required_argument, NULL, 'r' },
          { "output_file", required_argument, NULL, 'o' },
          { "chisq_file", required_argument, NULL, 'p' },
          { "universal_time", required_argument, NULL, 't' },
          { "lls_file", required_argument, NULL, 'l' },
          { "lcurve_file", required_argument, NULL, 'k' },
          { "alpha_int", required_argument, NULL, 'c' },
          { "alpha_sh", required_argument, NULL, 'd' },
          { "alpha_tor", required_argument, NULL, 'j' },
          { "maxit", required_argument, NULL, 'q' },
          { "print_data", no_argument, NULL, 'u' },
          { 0, 0, 0, 0 }
        };

      c = getopt_long(argc, argv, "a:b:c:d:e:f:g:h:j:k:l:m:n:o:p:q:r:t:u", long_options, &option_index);
      if (c == -1)
        break;

      switch (c)
        {
          case 'n':
            nmax_int = (size_t) atoi(optarg);
            break;

          case 'm':
            mmax_int = (size_t) atoi(optarg);
            break;

          case 'a':
            nmax_tor = (size_t) atoi(optarg);
            break;

          case 'b':
            mmax_tor = (size_t) atoi(optarg);
            break;

          case 'e':
            nmax_sh = (size_t) atoi(optarg);
            break;

          case 'f':
            mmax_sh = (size_t) atoi(optarg);
            break;

          case 'g':
            nmax_ext = (size_t) atoi(optarg);
            break;

          case 'h':
            mmax_ext = (size_t) atoi(optarg);
            break;

          case 'c':
            alpha_int = atof(optarg);
            break;

          case 'd':
            alpha_sh = atof(optarg);
            break;

          case 'j':
            alpha_tor = atof(optarg);
            break;

          case 'r':
            residual_file = optarg;
            break;

          case 'k':
            Lcurve_file = optarg;
            break;

          case 'o':
            output_file = optarg;
            break;

          case 't':
            universal_time = atof(optarg);
            break;

          case 'p':
            chisq_file = optarg;
            break;

          case 'l':
            lls_file = optarg;
            break;

          case 'q':
            robust_maxit = (size_t) atoi(optarg);
            break;

          case 'u':
            print_data = 1;
            break;

          default:
            break;
        }
    }

  while (optind < argc)
    {
      fprintf(stderr, "main: reading %s...", argv[optind]);
      gettimeofday(&tv0, NULL);
      mdata = magdata_read(argv[optind], mdata);
      gettimeofday(&tv1, NULL);

      if (!mdata)
        exit(1);

      fprintf(stderr, "done (%zu data total, %g seconds)\n",
              mdata->n, time_diff(tv0, tv1));

      ++optind;
    }

  if (!mdata)
    {
      print_help(argv);
      exit(1);
    }

  mmax_int = GSL_MIN(mmax_int, nmax_int);
  mmax_ext = GSL_MIN(mmax_ext, nmax_ext);
  mmax_sh = GSL_MIN(mmax_sh, nmax_sh);
  mmax_tor = GSL_MIN(mmax_tor, nmax_tor);

  fprintf(stderr, "main: universal time = %.1f\n", universal_time);

  fprintf(stderr, "main: nmax_int  = %zu\n", nmax_int);
  fprintf(stderr, "main: mmax_int  = %zu\n", mmax_int);
  fprintf(stderr, "main: nmax_ext  = %zu\n", nmax_ext);
  fprintf(stderr, "main: mmax_ext  = %zu\n", mmax_ext);
  fprintf(stderr, "main: nmax_sh   = %zu\n", nmax_sh);
  fprintf(stderr, "main: mmax_sh   = %zu\n", mmax_sh);
  fprintf(stderr, "main: nmax_tor  = %zu\n", nmax_tor);
  fprintf(stderr, "main: mmax_tor  = %zu\n", mmax_tor);
  fprintf(stderr, "main: alpha_int = %g\n", alpha_int);
  fprintf(stderr, "main: alpha_sh  = %g\n", alpha_sh);
  fprintf(stderr, "main: alpha_tor = %g\n", alpha_tor);

  if (residual_file)
    fprintf(stderr, "main: residual file = %s\n", residual_file);

  if (Lcurve_file)
    fprintf(stderr, "main: L-curve file  = %s\n", Lcurve_file);

  /*
   * re-compute flags for fitting components / gradient, etc;
   * must be called before magdata_init()
   */
  set_flags(mdata);

  fprintf(stderr, "main: initializing spatial weighting histogram...");
  gettimeofday(&tv0, NULL);
  magdata_init(mdata);
  gettimeofday(&tv1, NULL);
  fprintf(stderr, "done (%g seconds)\n", time_diff(tv0, tv1));

  /* re-compute weights, nvec, nres based on flags update */
  fprintf(stderr, "main: computing spatial weighting of data...");
  gettimeofday(&tv0, NULL);
  magdata_calc(mdata);
  gettimeofday(&tv1, NULL);
  fprintf(stderr, "done (%g seconds)\n", time_diff(tv0, tv1));

#if POLTOR_SYNTH_DATA
  fprintf(stderr, "main: setting unit spatial weights...");
  magdata_unit_weights(mdata);
  fprintf(stderr, "done\n");
#endif

  fprintf(stderr, "main: print_data = %d\n", print_data);
  if (print_data)
    {
      fprintf(stderr, "main: writing data to %s...", data_file);
      magdata_print(data_file, mdata);
      fprintf(stderr, "done\n");

      fprintf(stderr, "main: writing data map to %s...", datamap_file);
      magdata_map(datamap_file, mdata);
      fprintf(stderr, "done\n");
    }

  fprintf(stderr, "main: satellite rmin = %.1f (%.1f) [km]\n",
          mdata->rmin, mdata->rmin - mdata->R);
  fprintf(stderr, "main: satellite rmax = %.1f (%.1f) [km]\n",
          mdata->rmax, mdata->rmax - mdata->R);

  params.R = R;
  params.b = b;
  params.d = d;
  params.rmin = GSL_MAX(mdata->rmin, mdata->R + 250.0);
  params.rmax = GSL_MIN(mdata->rmax, mdata->R + 450.0);
  params.nmax_int = nmax_int;
  params.mmax_int = mmax_int;
  params.nmax_ext = nmax_ext;
  params.mmax_ext = mmax_ext;
  params.nmax_sh = nmax_sh;
  params.mmax_sh = mmax_sh;
  params.nmax_tor = nmax_tor;
  params.mmax_tor = mmax_tor;
  params.shell_J = 0;
  params.data = mdata;
  params.alpha_int = alpha_int;
  params.alpha_sh = alpha_sh;
  params.alpha_tor = alpha_tor;

#if POLTOR_QD_HARMONICS
  params.flags = POLTOR_FLG_QD_HARMONICS;
#else
  params.flags = 0;
#endif

  poltor_p = poltor_alloc(&params);

  fprintf(stderr, "main: poltor rmin = %.1f (%.1f) [km]\n",
          params.rmin, params.rmin - mdata->R);
  fprintf(stderr, "main: poltor rmax = %.1f (%.1f) [km]\n",
          params.rmax, params.rmax - mdata->R);

#if POLTOR_SYNTH_DATA
  fprintf(stderr, "main: replacing with synthetic data...");
  gettimeofday(&tv0, NULL);
  poltor_synth(poltor_p);
  gettimeofday(&tv1, NULL);
  fprintf(stderr, "done (%g seconds)\n", time_diff(tv0, tv1));
#endif

  if (lls_file)
    {
      /* use previously computed LS system from file */
      fprintf(stderr, "main: loading LS system from %s...", lls_file);
      lls_complex_load(lls_file, poltor_p->lls_workspace_p);
      fprintf(stderr, "done\n");

      /* solve LS system */
      poltor_solve(poltor_p);
    }
  else
    {
      size_t maxiter = robust_maxit;
      size_t iter = 0;
      char buf[2048];

#if POLTOR_SYNTH_DATA
      maxiter = 1;
#endif

      while (iter++ < maxiter)
        {
          fprintf(stderr, "main: ROBUST ITERATION %zu/%zu\n", iter, maxiter);

          /* build LS system */
          poltor_calc(poltor_p);

          /* solve LS system */
          poltor_solve(poltor_p);

          sprintf(buf, "%s.iter%zu", spectrum_file, iter);
          fprintf(stderr, "main: printing spectrum to %s...", buf);
          poltor_print_spectrum(buf, poltor_p);
          fprintf(stderr, "done\n");
        }
    }

  print_coefficients(poltor_p);

  fprintf(stderr, "main: printing correlation data to %s...", corr_file);
  print_correlation(corr_file, poltor_p);
  fprintf(stderr, "done\n");

  fprintf(stderr, "main: printing spectrum to %s...", spectrum_file);
  poltor_print_spectrum(spectrum_file, poltor_p);
  fprintf(stderr, "done\n");

  if (Lcurve_file)
    {
      fprintf(stderr, "main: writing L-curve data to %s...", Lcurve_file);
      print_Lcurve(Lcurve_file, poltor_p);
      fprintf(stderr, "done\n");
    }

  if (output_file)
    {
      fprintf(stderr, "main: writing output coefficients to %s...", output_file);
      poltor_write(output_file, poltor_p);
      fprintf(stderr, "done\n");
    }

  if (residual_file)
    {
      fprintf(stderr, "main: printing residuals to %s...", residual_file);
      print_residuals(residual_file, poltor_p);
      fprintf(stderr, "done\n");
    }

  if (chisq_file)
    {
      fprintf(stderr, "main: printing chisq/dof to %s...", chisq_file);
      print_chisq(chisq_file, poltor_p);
      fprintf(stderr, "done\n");
    }

  magdata_free(mdata);
  poltor_free(poltor_p);

  return 0;
} /* main() */