Beispiel #1
0
/* Routines that handle the eigensolver.
 *
 * Linear stability analysis
 * Solve J z = t M z
 *
 * where 
 *
 * input:
 * J = jacobian matrix 
 * M = mass or overlap matrix
 *
 * output:
 * z = eigenvectors
 * t = eigenvalues
 *
 * Friendly warning:
 * Do not edit this unless you know what you are doing!!
 *
 * Originally written by Ian Gates
 * pre-CVS modification history:
 *   - Sep 24, 1997, first checkin
 *   - Feb 98 -> Oct 98, another checkin
 *   - Jan 13, 2000, MMH rearranged and conformed to Goma style.
 */
void
eggrollwrap(int *istuff,	/* info for eigenvalue extraction */
	    dbl *dstuff,	/* info for eigenvalue extraction */
	    
	    int *ija,		/* column pointer array */
	    dbl *jac,		/* nonzero array */
	    dbl *mas,		/* nonzero array - same structure 
				   as jac[] (ija[]) */
	    
	    dbl *x,		/* Value of the solution vector */
	    char *ExoFileOut,	/* Name of exoII output file */
	    int prob_type,
	    dbl delta_t,	/* time step size */
	    dbl theta,		/* variable time integration parameter
				   explicit (theta = 1) to 
				   implicit (theta = 0) */
	    dbl *x_old,		/* Value of the old solution vector */
	    dbl *xdot,		/* Value of xdot predicted for new 
				   solution */
	    dbl *xdot_old,      /* dx/dt at previous time step */
	    dbl *resid_vector,
	    int *converged,	/* whether the Newton has converged */
	    int *nprint,	/* counter for time step number */
	    int tnv,		/* number of nodal results */
	    int tnv_post,	/* number of post processing results */
	    struct Results_Description *rd,
	    int *gindex,
	    int *p_gsize,
	    dbl	*gvec,
	    dbl time_value,
	    Exo_DB *exo,	/* ptr to finite element mesh db */
	    int Num_Proc,	/* number of processors used */
	    Dpi	*dpi)		/* ptr to distributed processing info */
{
  int 
    i, j, ic, 
    nj, nnz_j, 
    first_linear_solver_call, Factor_Flag, matr_form, 
    error, rcflag, action, 
    ev_n, ev_jac, 
    filter, 
    mm, max_itr,
    nev_want, nev_found, lead, 
    /*    read_form, soln_tech, push_mode, */
    push_mode, 
    init_shft, recycle;
  dbl
    stol, ivector,
    dwork[20]; 
  dbl 
    *ev_e, *ev_i, *ev_r, *ev_x,  
    *v1, *v2, 
    *mat, 
    **evect, **schur;
  char save_ExoFileOut[MAX_FNL];

  static int UMF_system_id;	/* Used to uniquely identify the
				 * explicit fill system to solve from
				 * the other UMF systems. */
  /* Initialize
   */
  ic = error = rcflag = action = 0;
  ev_jac = 0;
  matr_form = 1;

  /* Set values
   */
  mm         = istuff[0];
  nj         = istuff[1];
  nnz_j      = istuff[2];
  filter     = istuff[3];
  recycle    = istuff[4];
  nev_want   = istuff[6];
  init_shft  = istuff[7];
  max_itr    = istuff[8];
  push_mode  = istuff[9];
  stol       = dstuff[0];
  ivector    = dstuff[3];

  printf(" Initializing variables and allocating space... ");

  /* Allocate spectrum storage
   */
  ev_e = Dvector_birth(mm+5);
  ev_i = Dvector_birth(mm+5);
  ev_r = Dvector_birth(mm+5);
  ev_x = Dvector_birth(mm+5);

  /* Set initial (real) shifts
   */
  ev_n = init_shft;
  vcopy(init_shft, &ev_r[0], 1.0, &dstuff[10]);

  /* Allocate auxiliary work vectors
   */
  mat = Dvector_birth(nnz_j+5);

  /* Allocate eigenvectors and schur storage
   */
  i = nj+5;
  j = mm+5; 
  evect = Dmatrix_birth(j, i);
  schur = Dmatrix_birth(j, i);

  /* Allocate reverse communication vectors
   */
  v1 = Dvector_birth(nj+5);
  v2 = Dvector_birth(nj+5);

  /* Check for something that seems to make no difference if it's on,
   * except for occasionally causing seg faults... */
  if(recycle != 0)
    EH(-1, "Eigen recycle currently doesn't work, turn it off.");

  /* Set initial vector
   */
  vinit(nj, &v1[0], 0.5);

  /* GEVP solution
   */
  ic = 0;
  first_linear_solver_call = +1;
  do {
    ic++;
    /* printf("ic = %d\n", ic); fflush(stdout); */
    gevp_solver_rc(nj, mm, max_itr, stol, filter, &ev_n, &ev_r[0],
		   &ev_i[0], &ev_e[0], &ev_x[0], &lead, ev_jac,
		   nev_want, &nev_found, schur, evect, recycle,
		   ivector, 0, &rcflag, &action, &dwork[0], &v1[0],
		   &v2[0]);
    /* printf("action = %d\n", action); fflush(stdout); */
    switch (action)
      {
      case  0: /* All done */
	break;  
      case  1: /* v2 = J*v1 */
	MV_MSR(&nj, &ija[0], &jac[0], &v1[0], &v2[0]);
	break;  
      case  2: /* v2 = M*v1 */
	MV_MSR(&nj, &ija[0], &mas[0], &v1[0], &v2[0]);
	break;  
      case  3: /* inv(J-sM) */
	/* Shift matrix step */
	v2sum(nnz_j, &mat[0], 1.0, &jac[0], -dwork[0], &mas[0]);

	/* Invert step - get LU for later */
	if(first_linear_solver_call == 1)
	  {
	    Factor_Flag = -2;
	    UMF_system_id = -1;
	  }
	else
	  Factor_Flag = -1;

	/*
	printf("Calling SL_UMF, first_linear_solver_call = %d, Factor_Flag = %d\n",
	       first_linear_solver_call, Factor_Flag); fflush(stdout); 
	*/

	UMF_system_id = SL_UMF(UMF_system_id,
			       &first_linear_solver_call, 
			       &Factor_Flag, 
			       &matr_form, 
			       &nj, 
			       &nnz_j, 
			       &ija[0], 
			       &ija[0], 
			       &mat[0], 
			       &v1[0], 
			       &v2[0]);
	first_linear_solver_call = 0;
	break;
      case  4: /* v2 = inv(J-sM)*M*v1 */
	Factor_Flag = 3;
	if(first_linear_solver_call)
	  EH(-1, "Tried to transform eigenvectors before a solve!");
	gevp_transformation(UMF_system_id, first_linear_solver_call,
			    Factor_Flag, matr_form, 1, nj, nnz_j,
			    &ija[0], &jac[0], &mas[0], &mat[0],
			    /*			  soln_tech, */
			    &v2[0], &v1[0], dwork[0], dwork[1]);
	break;
      default:
	EH(-1, "Uh-oh!  I shouldn't be here!");
	break;
      } /* switch(action) */
    if (ic > 10000)
      error = 1;
  } while ((rcflag != 0) && (error == 0));

  /* Error check
   */
  if (error == 1)
    {
      puts(" E: Too many iterations.  Escape.  ");
      exit(-1);
    }

  /* De-allocate solver storage
   */  

  first_linear_solver_call = -1;

  /* MMH sez: If first_linear_solver_call == -1, then we want to
   * deallocate memory so we shouldn't be trying to solve anything!
   * This was FMR'ing b/c SL_UMF was being called with
   * first_linear_solver_call = -1, and Factor_Flag = 3.  Bad.
   */
  Factor_Flag = -3;

  UMF_system_id = SL_UMF(UMF_system_id,
			 &first_linear_solver_call, 
			 &Factor_Flag, 
			 &matr_form, 
			 &nj, 
			 &nnz_j, 
			 ija, 
			 ija, 
			 mat, 
			 &v1[0], 
			 &v2[0]);  
  
  /* Display results 
   */
  printf("\n-------------------------------------------------------------------------------\n");
  if(Linear_Stability == LSA_3D_OF_2D)
    printf("NORMAL MODE WAVE NUMBER = %g\n", LSA_3D_of_2D_wave_number);
  printf(" Eigensolver required %d iterations.\n",ic);
  printf(" Found %d converged eigenvalues.\n", nev_found);
  printf(" Leading Eigenvalue  = % 10.6e%+10.6e i RES = % 10.6e\n", 
	 ev_r[lead], ev_i[lead], ev_e[lead]);
  printf("    Real           Imag           RES\n");
  for (i=0;i<nev_found;i++)
    printf(" % 10.6e %+10.6e i % 10.6e\n", ev_r[i], ev_i[i], ev_e[i]);

  /* MMH: I know this is stupid, but the filename for the "regular"
   * Exodus output is a global variable!!!  It is required in
   * post_process_nodal().  I swap it out here, and will swap it back
   * when we're done with LSA.  Why don't I just overwrite it
   * completely you may ask?  Well, I don't know if and/or when the
   * code will continue to do something useful after LSA.  If it ever
   * does, then it would probably like to know what the correct output
   * filename is.  Kinda like camping: Leave with what you came in
   * with.  */
  strncpy(save_ExoFileOut, ExoFileOut, MAX_FNL-1);

  /* Write results to file (exoII format)
   */
  printf(" push_mode                          = %12d  \n", push_mode);
  if (push_mode > 0)
    {
      puts(" Writing modes to file ...");
      /* Write to exo file
       * Each mode is written as a "time step" solution into exoII DB
       */
      for(i = 0; i < push_mode; i++)
	{
	  printf("\t\t Mode %4d ...", i);
	  if(LSA_3D_of_2D_wave_number == -1.0)
	    sprintf(ExoFileOut, "LSA_%d_of_%d_%s", i + 1, push_mode,
		    save_ExoFileOut);
	  else
	    sprintf(ExoFileOut, "LSA_%d_of_%d_wn=%g_%s", i + 1, push_mode,
		    LSA_3D_of_2D_wave_number, save_ExoFileOut);

	  /* Replicate basic mesh info */
	  one_base(exo);
	  wr_mesh_exo(exo, ExoFileOut, 0);
	  wr_result_prelim_exo(rd, exo, ExoFileOut, NULL);
	  /* Update exo file for distributed problem info 
	   */
	  if (Num_Proc > 1) {
	    wr_dpi(dpi, ExoFileOut, 0);
	  }
	  for (j = 0; j < tnv; j++) {
	    extract_nodal_vec(&evect[i][0], rd->nvtype[j], rd->nvkind[j], 
			      rd->nvmatID[j], gvec, exo, FALSE, time_value);
	    wr_nodal_result_exo(exo, ExoFileOut, gvec, j+1, 1, 
				time_value);
	  }

	  /*
	   *  Add additional user-specified post processing variables 
	   */
	  if (tnv_post > 0) {
	    post_process_nodal(&evect[i][0], NULL, x_old, xdot, xdot_old,
			       resid_vector, 1, &time_value, delta_t, 0.0,
                               NULL, exo, dpi, rd, ExoFileOut);
	  }
	  zero_base(exo);
	  printf(" recorded.\n");
	}
    }
  /* MMH: See comments above. */
  strncpy(ExoFileOut, save_ExoFileOut, MAX_FNL);

  /* De-allocate work vectors
   */
  printf("Deallocating memory ... ");
  i = nj+5;
  j = mm+5;
  Dmatrix_death(schur, j, i);
  Dmatrix_death(evect, j, i);
  Dvector_death(&v2[0], nj+5);
  Dvector_death(&v1[0], nj+5);
  Dvector_death(&mat[0], nnz_j+5);
  Dvector_death(&ev_e[0], mm+5);
  Dvector_death(&ev_i[0], mm+5);
  Dvector_death(&ev_r[0], mm+5);
  Dvector_death(&ev_x[0], mm+5);
  printf("done.\n");
}
Beispiel #2
0
void 
write_solution(char output_file[], /* name EXODUS II file */
	       double resid_vector[], /* Residual vector */
	       double x[],	/* soln vector */
	       double **x_sens_p, /* sensitivity vectors */
	       double x_old[],	/* soln vector at previous time step */
	       double xdot[],	/* dx/dt */
	       double xdot_old[],/* dx/dt at previous time step */
	       int tev,		/* total elem variables
				   (normal) */
	       int tev_post,	/* additional post process
				   elem vars */
	       double *gv,      /* global variable values */
	       struct Results_Description  *rd, /* for post process vars
						   (rf_io_structs.h) */
	       int *gindex,
	       int *p_gsize,
	       double *gvec,
	       double ***gvec_elem, /* array vars [eb_index][ev_index][elem] */
	       int *nprint,	/* counter for time step number*/
	       dbl delta_t,	/* time step size */
	       dbl theta,  	/* time integration parameter */
	       dbl time_value,	/* current time value */
               dbl *x_pp,       /* post proc vars for export */
	       Exo_DB *exo,
	       Dpi *dpi)
    /*************************************************************************
     *
     * write_solution():
     *
     * This routine gathers both the solution and the post-processed
     * variables and then writes them one at a time to the output file.
     * The description of what it writes is taken from the
     * Results_Description structure in the parameter list.
     *
     *************************************************************************/
{
  int i, i_post, step=0;
#ifdef DEBUG
  static char *yo="write_solution";
  fprintf(stderr, "%s: begins\n", yo);
#endif

  /* First nodal quantities */
  for (i = 0; i < rd->TotalNVSolnOutput; i++) {
    extract_nodal_vec(x, rd->nvtype[i], rd->nvkind[i], rd->nvmatID[i],
		      gvec, exo, FALSE, time_value);
    step = (*nprint)+1;
    wr_nodal_result_exo(exo, output_file, gvec, i+1, step, time_value);
  }

#ifdef DEBUG
  fprintf(stderr, "%s: done with regular nodal vars; start tnv_post\n", yo);
#endif

  /*
   *  Add additional user-specified post processing variables
   */
  if (rd->TotalNVPostOutput > 0) {
    step = (*nprint) + 1;
#ifdef DEBUG
    fprintf(stderr, "%s: start post_process_nodal\n", yo);
#endif

    post_process_nodal(x, x_sens_p, x_old, xdot, xdot_old, resid_vector, 
		       step, &time_value, delta_t, theta, x_pp,
		       exo, dpi, rd, output_file);
#ifdef DEBUG
    fprintf(stderr, "%s: done w/ post_process_nodal\n", yo);
#endif

    /*
     *  Write out time derivatives if requested
     */
    if (TIME_DERIVATIVES != -1 && (TimeIntegration != STEADY)) {
      for (i = 0; i < rd->TotalNVSolnOutput; i++) {
	i_post = rd->TotalNVSolnOutput + rd->TotalNVPostOutput + i;
	extract_nodal_vec(xdot, rd->nvtype[i_post], rd->nvkind[i_post],
			  rd->nvmatID[i], gvec, exo, TRUE, time_value);
	wr_nodal_result_exo(exo, output_file, gvec, i_post + 1, 
			    *nprint+1, time_value);
      }
    }
  }

  /* Now element quantities */
  for(i = 0; i < tev; i++) {
    extract_elem_vec(x, i, rd->evtype[i], gvec_elem, exo);
    step = (*nprint)+1;
    wr_elem_result_exo(exo, output_file, gvec_elem, i, step, 
		       time_value, rd);
  }
  /* Finally, global values */
  
  wr_global_result_exo( exo, output_file, step, rd->ngv, gv );
	
#ifdef DEBUG
  fprintf(stderr, "%s: done with regular element vars; start tev_post\n", yo);
#endif

  /* Add additional user-specified post processing variables */
  if (tev_post > 0) {
      step = (*nprint) + 1;
#ifdef DEBUG
      fprintf(stderr, "%s: start post_process_elem\n", yo);
#endif

      post_process_elem(x, x_old, xdot, xdot_old, resid_vector, tev, tev_post, 
			gvec_elem, step, &time_value, delta_t, exo, dpi, rd);
#ifdef DEBUG
      fprintf(stderr, "%s: done w/ post_process_elem\n", yo);
#endif

      /* Write out time derivatives if requested */
      if (TIME_DERIVATIVES != -1 && (TimeIntegration != STEADY)) {
	for (i = 0; i < tev; i++) {
	  i_post = tev_post + i;
	  extract_elem_vec(xdot, i_post, rd->evtype[i_post], gvec_elem, exo);
	  wr_elem_result_exo(exo, output_file, gvec_elem, i_post,
			     *nprint+1, time_value, rd);
	}
      }
  }
}