Exemplo n.º 1
0
int sp_num_alloc(sp_num** N, int n, ErrorMsg error_message){
	int maxnz, k;
	class_alloc((*N),sizeof(sp_num),error_message);
	printf("calling spnumalloc");
	maxnz = n*(n+1);
	maxnz /=2;
	(*N)->n = n;
	class_call(sp_mat_alloc(&((*N)->L), n, n, maxnz, error_message),
		error_message,error_message);
	class_call(sp_mat_alloc(&((*N)->U), n, n, maxnz, error_message),
		error_message,error_message);
	class_alloc((*N)->xi,n*sizeof(int*),error_message);
	/* I really want xi to be a vector of pointers to vectors. */
	class_alloc((*N)->xi[0],n*n*sizeof(int),error_message);
	for (k=1;k<n;k++)	(*N)->xi[k] = (*N)->xi[k-1]+n;
	/*Assign pointers to rows.*/
	class_alloc((*N)->topvec,n*sizeof(int),error_message);
	class_alloc((*N)->pinv,n*sizeof(int),error_message);
	class_alloc((*N)->p,n*sizeof(int),error_message);
	/* Has to be n+1 because sp_amd uses it for storage:*/
	class_alloc((*N)->q,(n+1)*sizeof(int),error_message);
	class_alloc((*N)->w,n*sizeof(double),error_message);
	class_alloc((*N)->wamd,(8*(n+1))*sizeof(int),error_message);
	return _SUCCESS_;
}
Exemplo n.º 2
0
int parser_read_file(
		     char * filename,
		     struct file_content * pfc,
		     ErrorMsg errmsg
		     ){
  FILE * inputfile;
  char line[_LINE_LENGTH_MAX_];
  int counter;
  int is_data;
  FileArg name;
  FileArg value;

  class_open(inputfile,filename,"r",errmsg);

  counter = 0;
  while (fgets(line,_LINE_LENGTH_MAX_,inputfile) != NULL) {
    class_call(parser_read_line(line,&is_data,name,value,errmsg),errmsg,errmsg);
    if (is_data == _TRUE_) counter++;
  }

  class_test(counter == 0,
	     errmsg,
	     "No readable input in file %s",filename);

  class_alloc(pfc->filename,(strlen(filename)+1)*sizeof(char),errmsg);
  strcpy(pfc->filename,filename);

  class_call(parser_init(pfc,counter,errmsg),
	     errmsg,
	     errmsg);

  rewind(inputfile);

  counter = 0;
  while (fgets(line,_LINE_LENGTH_MAX_,inputfile) != NULL) {
    class_call(parser_read_line(line,&is_data,name,value,errmsg),errmsg,errmsg);
    if (is_data == _TRUE_) {
      strcpy(pfc->name[counter],name);
      strcpy(pfc->value[counter],value);
      pfc->read[counter]=_FALSE_;
      counter++;
    }
  }

  fclose(inputfile);

  return _SUCCESS_;

}
Exemplo n.º 3
0
std::string get_single_class(SEXP x) {
  SEXP klass = Rf_getAttrib(x, R_ClassSymbol);
  if (!Rf_isNull(klass)) {
    CharacterVector classes(klass);
    return collapse_utf8(classes, "/");
  }

  if (Rf_isMatrix(x)) {
    return "matrix";
  }

  switch (TYPEOF(x)) {
  case RAWSXP:
    return "raw";
  case INTSXP:
    return "integer";
  case REALSXP :
    return "numeric";
  case LGLSXP:
    return "logical";
  case STRSXP:
    return "character";
  case CPLXSXP:
    return "complex";

  case VECSXP:
    return "list";
  default:
    break;
  }

  // just call R to deal with other cases
  // we could call R_data_class directly but we might get a "this is not part of the api"
  RObject class_call(Rf_lang2(Rf_install("class"), x));
  klass = Rf_eval(class_call, R_GlobalEnv);
  return CHAR(STRING_ELT(klass, 0));
}
Exemplo n.º 4
0
int evolver_ndf15(
		  int (*derivs)(double x,double * y,double * dy,
				void * parameters_and_workspace, ErrorMsg error_message),
		  double x_ini,
		  double x_final,
		  double * y_inout,
		  int * used_in_output,
		  int neq,
		  void * parameters_and_workspace_for_derivs,
		  double rtol,
		  double minimum_variation,
		  int (*timescale_and_approximation)(double x,
						     void * parameters_and_workspace,
						     double * timescales,
						     ErrorMsg error_message),
		  double timestep_over_timescale,
		  double * t_vec,
		  int tres,
		  int (*output)(double x,double y[],double dy[],int index_x,void * parameters_and_workspace,
				ErrorMsg error_message),
		  int (*print_variables)(double x, double y[], double dy[], void *parameters_and_workspace,
					 ErrorMsg error_message),
		  ErrorMsg error_message){

  /* Constants: */
  double G[5]={1.0,3.0/2.0,11.0/6.0,25.0/12.0,137.0/60.0};
  double alpha[5]={-37.0/200,-1.0/9.0,-8.23e-2,-4.15e-2, 0};
  double invGa[5],erconst[5];
  double abstol = 1e-18, eps=1e-19, threshold=abstol;
  int maxit=4, maxk=5;

  /* Logicals: */
  int Jcurrent,havrate,done,at_hmin,nofailed,gotynew,tooslow,*interpidx;

  /* Storage: */
  double *f0,*y,*wt,*ddfddt,*pred,*ynew,*invwt,*rhs,*psi,*difkp1,*del,*yinterp;
  double *tempvec1,*tempvec2,*ypinterp,*yppinterp;
  double **dif;
  struct jacobian jac;
  struct numjac_workspace nj_ws;

  /* Method variables: */
  double t,t0,tfinal,tnew=0;
  double rh,htspan,absh,hmin,hmax,h,tdel;
  double abshlast,hinvGak,minnrm,oldnrm=0.,newnrm;
  double err,hopt,errkm1,hkm1,errit,rate=0.,temp,errkp1,hkp1,maxtmp;
  int k,klast,nconhk,iter,next,kopt,tdir;

  /* Misc: */
  int stepstat[6],nfenj,j,ii,jj, numidx, neqp=neq+1;
  int verbose=0;

  /** Allocate memory . */

  void * buffer;
  int buffer_size;

  buffer_size=
    15*neqp*sizeof(double)
    +neqp*sizeof(int)
    +neqp*sizeof(double*)
    +(7*neq+1)*sizeof(double);

  class_alloc(buffer,
	      buffer_size,
	      error_message);

  f0       =(double*)buffer;
  wt       =f0+neqp;
  ddfddt   =wt+neqp;
  pred     =ddfddt+neqp;
  y        =pred+neqp;
  invwt    =y+neqp;
  rhs      =invwt+neqp;
  psi      =rhs+neqp;
  difkp1   =psi+neqp;
  del      =difkp1+neqp;
  yinterp  =del+neqp;
  ypinterp =yinterp+neqp;
  yppinterp=ypinterp+neqp;
  tempvec1 =yppinterp+neqp;
  tempvec2 =tempvec1+neqp;

  interpidx=(int*)(tempvec2+neqp);

  dif      =(double**)(interpidx+neqp);
  dif[1]   =(double*)(dif+neqp);
  for(j=2;j<=neq;j++) dif[j] = dif[j-1]+7; /* Set row pointers... */
  dif[0] = NULL;
  /* for (ii=0;ii<(7*neq+1);ii++) dif[1][ii]=0.; */
  for (j=1; j<=neq; j++) {
    for (ii=1;ii<=7;ii++) {
      dif[j][ii]=0.;
    }
  }

  /* 	class_alloc(f0,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(wt,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(ddfddt,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(pred,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(y,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(invwt,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(rhs,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(psi,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(difkp1,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(del,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(yinterp,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(ypinterp,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(yppinterp,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(tempvec1,sizeof(double)*neqp,error_message); */
  /* 	class_alloc(tempvec2,sizeof(double)*neqp,error_message); */

  /* 	class_alloc(interpidx,sizeof(int)*neqp,error_message); */

  /* Allocate vector of pointers to rows of dif:*/
  /* 	class_alloc(dif,sizeof(double*)*neqp,error_message);  */
  /* 	class_calloc(dif[1],(7*neq+1),sizeof(double),error_message); */
  /* 	dif[0] = NULL; */
  /* 	for(j=2;j<=neq;j++) dif[j] = dif[j-1]+7; */ /* Set row pointers... */

  /*Set pointers:*/
  ynew = y_inout-1; /* This way y_inout is always up to date. */

  /*Initialize the jacobian:*/
  class_call(initialize_jacobian(&jac,neq,error_message),error_message,error_message);

  /* Initialize workspace for numjac: */
  class_call(initialize_numjac_workspace(&nj_ws,neq,error_message),error_message,error_message);

  /* Initialize some method parameters:*/
  for(ii=0;ii<5;ii++){
    invGa[ii] = 1.0/(G[ii]*(1.0 - alpha[ii]));
    erconst[ii] = alpha[ii]*G[ii] + 1.0/(2.0+ii);
  }

  /* Set the relevant indices which needs to be found by interpolation. */
  /* But if we want to print variables for testing purposes, just interpolate everything.. */
  for(ii=1;ii<=neq;ii++){
    y[ii] = y_inout[ii-1];
    if (print_variables==NULL){
      interpidx[ii]=used_in_output[ii-1];
    }
    else{
      interpidx[ii]=1;
    }
  }
  t0 = x_ini;
  tfinal = x_final;

  /* Some CLASS-specific stuff:*/
  next=0;
  while (t_vec[next] < t0) next++;

  if (verbose > 1){
    numidx=0;
    for(ii=1;ii<=neq;ii++){
      if (interpidx[ii]==_TRUE_) numidx++;
    }
    printf("%d/%d ",numidx,neq);
  }

  htspan = fabs(tfinal-t0);
  for(ii=0;ii<6;ii++) stepstat[ii] = 0;

  class_call((*derivs)(t0,y+1,f0+1,parameters_and_workspace_for_derivs,error_message),error_message,error_message);
  stepstat[2] +=1;
  if ((tfinal-t0)<0.0){
    tdir = -1;
  }
  else{
    tdir = 1;
  }
  hmax = (tfinal-t0)/10.0;
  t = t0;


  nfenj=0;
  class_call(numjac((*derivs),t,y,f0,&jac,&nj_ws,abstol,neq,
		    &nfenj,parameters_and_workspace_for_derivs,error_message),
	     error_message,error_message);
  stepstat[3] += 1;
  stepstat[2] += nfenj;
  Jcurrent = _TRUE_; /* True */

  hmin = 1.e-20;//16.0*eps*fabs(t);
  /*Calculate initial step */
  rh = 0.0;

  for(jj=1;jj<=neq;jj++){
    wt[jj] = MAX(fabs(y[jj]),threshold);
    /*printf("wt: %4.8f \n",wt[jj]);*/
    rh = MAX(rh,1.25/sqrt(rtol)*fabs(f0[jj]/wt[jj]));
  }

  absh = MIN(hmax, htspan);
  if (absh * rh > 1.0) absh = 1.0 / rh;

  absh = MAX(absh, hmin);
  h = tdir * absh;
  tdel = (t + tdir*MIN(sqrt(eps)*MAX(fabs(t),fabs(t+h)),absh)) - t;

  class_call((*derivs)(t+tdel,y+1,tempvec1+1,parameters_and_workspace_for_derivs,error_message),
	     error_message,error_message);
  stepstat[2] += 1;

  /*I assume that a full jacobi matrix is always calculated in the beginning...*/
  for(ii=1;ii<=neq;ii++){
    ddfddt[ii]=0.0;
    for(jj=1;jj<=neq;jj++){
      ddfddt[ii]+=(jac.dfdy[ii][jj])*f0[jj];
    }
  }

  rh = 0.0;
  for(ii=1;ii<=neq;ii++){
    ddfddt[ii] += (tempvec1[ii] - f0[ii]) / tdel;
    rh = MAX(rh,1.25*sqrt(0.5*fabs(ddfddt[ii]/wt[ii])/rtol));
  }
  absh = MIN(hmax, htspan);
  if (absh * rh > 1.0) absh = 1.0 / rh;

  absh = MAX(absh, hmin);
  h = tdir * absh;
  /* Done calculating initial step
     Get ready to do the loop:*/
  k = 1;			/*start at order 1 with BDF1	*/
  klast = k;
  abshlast = absh;

  for(ii=1;ii<=neq;ii++) dif[ii][1] = h*f0[ii];

  hinvGak = h*invGa[k-1];
  nconhk = 0; 	/*steps taken with current h and k*/
  class_call(new_linearisation(&jac,hinvGak,neq,error_message),
	     error_message,error_message);
  stepstat[4] += 1;
  havrate = _FALSE_; /*false*/

  /* Doing main loop: */
  done = _FALSE_;
  at_hmin = _FALSE_;
  while (done==_FALSE_){
    hmin = minimum_variation;
    maxtmp = MAX(hmin,absh);
    absh = MIN(hmax, maxtmp);
    if (fabs(absh-hmin)<100*eps){
      /* If the stepsize has not changed */
      if (at_hmin==_TRUE_){
	absh = abshlast;	/*required by stepsize recovery */
      }
      at_hmin = _TRUE_;
    }
    else{
      at_hmin = _FALSE_;
    }
    h = tdir * absh;
    /* Stretch the step if within 10% of tfinal-t. */
    if (1.1*absh >= fabs(tfinal - t)){
      h = tfinal - t;
      absh = fabs(h);
      done = _TRUE_;
    }
    if (((fabs(absh-abshlast)/absh)>1e-6)||(k!=klast)){
      adjust_stepsize(dif,(absh/abshlast),neq,k);
      hinvGak = h * invGa[k-1];
      nconhk = 0;
      class_call(new_linearisation(&jac,hinvGak,neq,error_message),
		 error_message,error_message);
      stepstat[4] += 1;
      havrate = _FALSE_;
    }
    /*		Loop for advancing one step */
    nofailed = _TRUE_;
    for( ; ; ){
      gotynew = _FALSE_;	/* is ynew evaluated yet?*/
      while(gotynew==_FALSE_){
	/*Compute the constant terms in the equation for ynew.
	  Next FOR lop is just: psi = matmul(dif(:,1:k),(G(1:k) * invGa(k)))*/
	for(ii=1;ii<=neq;ii++){
	  psi[ii] = 0.0;
	  for(jj=1;jj<=k;jj++){
	    psi[ii] += dif[ii][jj]*G[jj-1]*invGa[k-1];
	  }
	}
	/* Predict a solution at t+h. */
	tnew = t + h;
	if (done==_TRUE_){
	  tnew = tfinal; /*Hit end point exactly. */
	}
	h = tnew - t; 		 /* Purify h. */
	for(ii=1;ii<=neq;ii++){
	  pred[ii] = y[ii];
	  for(jj=1;jj<=k;jj++){
	    pred[ii] +=dif[ii][jj];
	  }
	}
	eqvec(pred,ynew,neq);

	/*The difference, difkp1, between pred and the final accepted
	  ynew is equal to the backward difference of ynew of order
	  k+1. Initialize to zero for the iteration to compute ynew.
	*/

	minnrm = 0.0;
	for(j=1;j<=neq;j++){
	  difkp1[j] = 0.0;
	  maxtmp = MAX(fabs(ynew[j]),fabs(y[j]));
	  invwt[j] = 1.0 / MAX(maxtmp,threshold);
	  maxtmp = 100*eps*fabs(ynew[j]*invwt[j]);
	  minnrm = MAX(minnrm,maxtmp);
	}
	/* Iterate with simplified Newton method. */
	tooslow = _FALSE_;
	for(iter=1;iter<=maxit;iter++){
	  for (ii=1;ii<=neq;ii++){
	    tempvec1[ii]=(psi[ii]+difkp1[ii]);
	  }
	  class_call((*derivs)(tnew,ynew+1,f0+1,parameters_and_workspace_for_derivs,error_message),
		     error_message,error_message);
	  stepstat[2] += 1;
	  for(j=1;j<=neq;j++){
	    rhs[j] = hinvGak*f0[j]-tempvec1[j];
	  }

	  /*Solve the linear system A*x=del by using the LU decomposition stored in jac.*/
	  if (jac.use_sparse){
	    sp_lusolve(jac.Numerical, rhs+1, del+1);
	  }
	  else{
	    eqvec(rhs,del,neq);
	    lubksb(jac.LU,neq,jac.luidx,del);
	  }

	  stepstat[5]+=1;
	  newnrm = 0.0;
	  for(j=1;j<=neq;j++){
	    maxtmp = fabs(del[j]*invwt[j]);
	    newnrm = MAX(newnrm,maxtmp);
	  }
	  for(j=1;j<=neq;j++){
	    difkp1[j] += del[j];
	    ynew[j] = pred[j] + difkp1[j];
	  }
	  if (newnrm <= minnrm){
	    gotynew = _TRUE_;
	    break; /* Break Newton loop */
	  }
	  else if(iter == 1){
	    if (havrate==_TRUE_){
	      errit = newnrm * rate / (1.0 - rate);
	      if (errit <= 0.05*rtol){
		gotynew = _TRUE_;
		break; /* Break Newton Loop*/
	      }
	    }
	    else {
	      rate = 0.0;
	    }
	  }
	  else if(newnrm > 0.9*oldnrm){
	    tooslow = _TRUE_;
	    break; /*Break Newton lop */
	  }
	  else{
	    rate = MAX(0.9*rate, newnrm / oldnrm);
	    havrate = _TRUE_;
	    errit = newnrm * rate / (1.0 - rate);
	    if (errit <= 0.5*rtol){
	      gotynew = _TRUE_;
	      break; /* exit newton */
	    }
	    else if (iter == maxit){
	      tooslow = _TRUE_;
	      break; /*exit newton */
	    }
	    else if (0.5*rtol < errit*pow(rate,(maxit-iter))){
	      tooslow = _TRUE_;
	      break; /*exit Newton */
	    }
	  }
	  oldnrm = newnrm;
	}
	if (tooslow==_TRUE_){
	  stepstat[1] += 1;
	  /*	! Speed up the iteration by forming new linearization or reducing h. */
	  if (Jcurrent==_FALSE_){
	    class_call((*derivs)(t,y+1,f0+1,parameters_and_workspace_for_derivs,error_message),
		       error_message,error_message);
	    nfenj=0;
	    class_call(numjac((*derivs),t,y,f0,&jac,&nj_ws,abstol,neq,
			      &nfenj,parameters_and_workspace_for_derivs,error_message),
		       error_message,error_message);
	    stepstat[3] += 1;
	    stepstat[2] += (nfenj + 1);
	    Jcurrent = _TRUE_;
	  }
	  else if (absh <= hmin){
	   class_test(absh <= hmin, error_message,
		      "Step size too small: step:%g, minimum:%g, in interval: [%g:%g]\n",
		     absh,hmin,t0,tfinal);
	 }
	  else{
	    abshlast = absh;
	    absh = MAX(0.3 * absh, hmin);
	    h = tdir * absh;
	    done = _FALSE_;
	    adjust_stepsize(dif,(absh/abshlast),neq,k);
	    hinvGak = h * invGa[k-1];
	    nconhk = 0;
	  }
	  /* A new linearisation is needed in both cases */
	  class_call(new_linearisation(&jac,hinvGak,neq,error_message),
		     error_message,error_message);
	  stepstat[4] += 1;
	  havrate = _FALSE_;
	}
      }
      /*end of while loop for getting ynew
	difkp1 is now the backward difference of ynew of order k+1. */
      err = 0.0;
      for(jj=1;jj<=neq;jj++){
	err = MAX(err,fabs(difkp1[jj]*invwt[jj]));
      }
      err = err * erconst[k-1];
      if (err>rtol){
	/*Step failed */
	stepstat[1]+= 1;
	if (absh <= hmin){ //BEN FLAG: I REMOVED THIS FOR NO GOOD REASON!/
	  class_test(absh <= hmin, error_message,
		     "Step size too small: step:%g, minimum:%g, in interval: [%g:%g]\n",
		     absh,hmin,t0,tfinal);
	}
	abshlast = absh;
	if (nofailed==_TRUE_){
	  nofailed = _FALSE_;
	  hopt = absh * MAX(0.1, 0.833*pow((rtol/err),(1.0/(k+1))));
	  if (k > 1){
	    errkm1 = 0.0;
	    for(jj=1;jj<=neq;jj++){
	      errkm1 = MAX(errkm1,fabs((dif[jj][k]+difkp1[jj])*invwt[jj]));
	    }
	    errkm1 = errkm1*erconst[k-2];
	    hkm1 = absh * MAX(0.1, 0.769*pow((rtol/errkm1),(1.0/k)));
	    if (hkm1 > hopt){
	      hopt = MIN(absh,hkm1); 		/* don't allow step size increase */
	      k = k - 1;
	    }
	  }
	  absh = MAX(hmin, hopt);
	}
	else{
	  absh = MAX(hmin, 0.5 * absh);
	}
	h = tdir * absh;
	if (absh < abshlast){
	  done = _FALSE_;
	}
	adjust_stepsize(dif,(absh/abshlast),neq,k);
	hinvGak = h * invGa[k-1];
	nconhk = 0;
	class_call(new_linearisation(&jac,hinvGak,neq,error_message),
		   error_message,error_message);
	stepstat[4] += 1;
	havrate = _FALSE_;
      }
      else {
	break; /* Succesfull step */
      }
    }
    /* End of conditionless FOR loop */
    stepstat[0] += 1;

    /* Update dif: */
    for(jj=1;jj<=neq;jj++){
      dif[jj][k+2] = difkp1[jj] - dif[jj][k+1];
      dif[jj][k+1] = difkp1[jj];
    }
    for(j=k;j>=1;j--){
      for(ii=1;ii<=neq;ii++){
	dif[ii][j] += dif[ii][j+1];
      }
    }
    /** Output **/
    while ((next<tres)&&(tdir * (tnew - t_vec[next]) >= 0.0)){
      /* Do we need to write output? */
      if (tnew==t_vec[next]){
	class_call((*output)(t_vec[next],ynew+1,f0+1,next,parameters_and_workspace_for_derivs,error_message),
		   error_message,error_message);
// MODIFICATION BY LUC
// All print_variables have been moved to the end of time step
/*
	if (print_variables != NULL){
	  class_call((*print_variables)(t_vec[next],ynew+1,f0+1,
					parameters_and_workspace_for_derivs,error_message),
		     error_message,error_message);
	}
*/
      }
      else {
	/*Interpolate if we have overshot sample values*/
	interp_from_dif(t_vec[next],tnew,ynew,h,dif,k,yinterp,ypinterp,yppinterp,interpidx,neq,2);

	class_call((*output)(t_vec[next],yinterp+1,ypinterp+1,next,parameters_and_workspace_for_derivs,
			     error_message),error_message,error_message);

      }
      next++;
    }
    /** End of output **/
    if (done==_TRUE_) {
      break;
    }
    klast = k;
    abshlast = absh;
    nconhk = MIN(nconhk+1,maxk+2);
    if (nconhk >= k + 2){
      temp = 1.2*pow((err/rtol),(1.0/(k+1.0)));
      if (temp > 0.1){
	hopt = absh / temp;
      }
      else {
	hopt = 10*absh;
      }
      kopt = k;
      if (k > 1){
	errkm1 = 0.0;
	for(jj=1;jj<=neq;jj++){
	  errkm1 = MAX(errkm1,fabs(dif[jj][k]*invwt[jj]));
	}
	errkm1 = errkm1*erconst[k-2];
	temp = 1.3*pow((errkm1/rtol),(1.0/k));
	if (temp > 0.1){
	  hkm1 = absh / temp;
	}
	else {
	  hkm1 = 10*absh;
	}
	if (hkm1 > hopt){
	  hopt = hkm1;
	  kopt = k - 1;
	}
      }
      if (k < maxk){
	errkp1 = 0.0;
	for(jj=1;jj<=neq;jj++){
	  errkp1 = MAX(errkp1,fabs(dif[jj][k+2]*invwt[jj]));
	}
	errkp1 = errkp1*erconst[k];
	temp = 1.4*pow((errkp1/rtol),(1.0/(k+2.0)));
	if (temp > 0.1){
	  hkp1 = absh / temp;
	}
	else {
	  hkp1 = 10*absh;
	}
	if (hkp1 > hopt){
	  hopt = hkp1;
	  kopt = k + 1;
	}
      }
      if (hopt > absh){
	absh = hopt;
	if (k!=kopt){
	  k = kopt;
	}
      }
    }
    /* Advance the integration one step. */
    t = tnew;
    eqvec(ynew,y,neq);
    Jcurrent = _FALSE_;

// MODIFICATION BY LUC
    if (print_variables!=NULL){
      class_call((*derivs)(tnew,
		             ynew+1,
		             f0+1,
		             parameters_and_workspace_for_derivs,error_message),
	               error_message,
	               error_message);

        class_call((*print_variables)(tnew,ynew+1,f0+1,
					parameters_and_workspace_for_derivs,error_message),
		     error_message,error_message);
    }
// end of modification

  }

  /* a last call is compulsory to ensure that all quantitites in
     y,dy,parameters_and_workspace_for_derivs are updated to the
     last point in the covered range */
  class_call(
	     (*derivs)(tnew,
		       ynew+1,
		       f0+1,
		       parameters_and_workspace_for_derivs,error_message),
	     error_message,
	     error_message);

  if (verbose > 0){
    printf("\n End of evolver. Next=%d, t=%e and tnew=%e.",next,t,tnew);
    printf("\n Statistics: [%d %d %d %d %d %d] \n",stepstat[0],stepstat[1],
	   stepstat[2],stepstat[3],stepstat[4],stepstat[5]);
  }

  /** Deallocate memory */

  free(buffer);

  /* 	free(f0); */
  /* 	free(wt); */
  /* 	free(ddfddt); */
  /* 	free(pred); */
  /* 	free(y); */
  /* 	free(invwt); */
  /* 	free(rhs); */
  /* 	free(psi); */
  /* 	free(difkp1); */
  /* 	free(del); */
  /* 	free(yinterp); */
  /* 	free(ypinterp); */
  /* 	free(yppinterp); */
  /* 	free(tempvec1); */
  /* 	free(tempvec2); */

  /* 	free(interpidx); */
  /* 	free(dif[1]); */
  /* 	free(dif); */

  uninitialize_jacobian(&jac);
  uninitialize_numjac_workspace(&nj_ws);
  return _SUCCESS_;

} /*End of program*/
Exemplo n.º 5
0
int initialize_jacobian(struct jacobian *jac, int neq, ErrorMsg error_message){
  int i;

  if (neq>15){
    jac->use_sparse = 1;
  }
  else{
    jac->use_sparse = 0;
  }
  jac->max_nonzero = (int)(MAX(3*neq,0.20*neq*neq));
  jac->cnzmax = 12*jac->max_nonzero/5;

  /*Maximal number of non-zero entries to be considered sparse */
  jac->repeated_pattern = 0;
  jac->trust_sparse = 4;
  /* Number of times a pattern is repeated before we trust it. */
  jac->has_grouping = 0;
  jac->has_pattern = 0;
  jac->sparse_stuff_initialized=0;

  /*Setup memory for the pointers of the dense method:*/

  class_alloc(jac->dfdy,sizeof(double*)*(neq+1),error_message); /* Allocate vector of pointers to rows of matrix.*/
  class_alloc(jac->dfdy[1],sizeof(double)*(neq*neq+1),error_message);
  jac->dfdy[0] = NULL;
  for(i=2;i<=neq;i++) jac->dfdy[i] = jac->dfdy[i-1]+neq; /* Set row pointers... */

  class_alloc(jac->LU,sizeof(double*)*(neq+1),error_message); /* Allocate vector of pointers to rows of matrix.*/
  class_alloc(jac->LU[1],sizeof(double)*(neq*neq+1),error_message);
  jac->LU[0] = NULL;
  for(i=2;i<=neq;i++) jac->LU[i] = jac->LU[i-1]+neq; /* Set row pointers... */

  class_alloc(jac->LUw,sizeof(double)*(neq+1),error_message);
  class_alloc(jac->jacvec,sizeof(double)*(neq+1),error_message);
  class_alloc(jac->luidx,sizeof(int)*(neq+1),error_message);

  /*Setup memory for the sparse method, if used: */
  if (jac->use_sparse){
    jac->sparse_stuff_initialized = 1;

    jac->xjac=(double*)(jac->luidx+neq+1);
    jac->col_group=(int*)(jac->xjac+jac->max_nonzero);
    jac->col_wi=jac->col_group+neq;
    jac->Cp=jac->col_wi+neq;
    jac->Ci=jac->Cp+neq+1;

    class_alloc(jac->xjac,sizeof(double)*jac->max_nonzero,error_message);
    class_alloc(jac->col_group,sizeof(int)*neq,error_message);
    class_alloc(jac->col_wi,sizeof(int)*neq,error_message);
    class_alloc(jac->Cp,sizeof(int)*(neq+1),error_message);
    class_alloc(jac->Ci,sizeof(int)*jac->cnzmax,error_message);

    class_call(sp_num_alloc(&jac->Numerical, neq,error_message),
	       error_message,error_message);

    class_call(sp_mat_alloc(&jac->spJ, neq, neq, jac->max_nonzero,
			    error_message),error_message,error_message);

  }

  /* Initialize jacvec to sqrt(eps):*/
  for (i=1;i<=neq;i++) jac->jacvec[i]=1.490116119384765597872e-8;
  return _SUCCESS_;
}
Exemplo n.º 6
0
int numjac(
	   int (*derivs)(double x, double * y,double * dy,
			 void * parameters_and_workspace, ErrorMsg error_message),
	   double t, double *y, double *fval,
	   struct jacobian *jac, struct numjac_workspace *nj_ws,
	   double thresh, int neq, int *nfe, void * parameters_and_workspace_for_derivs,
	   ErrorMsg error_message){
  /*	Routine that computes the jacobian numerically. It is based on the numjac
	implementation in MATLAB, but a feature for recognising sparsity in the
	jacobian and taking advantage of that has been added.
  */
  double eps=1e-19, br=pow(eps,0.875),bl=pow(eps,0.75),bu=pow(eps,0.25);
  double facmin=pow(eps,0.78),facmax=0.1;
  int logjpos, pattern_broken;
  double tmpfac,difmax2=0.,del2,ffscale;
  int i,j,rowmax2;
  double maxval1,maxval2;
  int colmax,group,row,nz,nz2;
  double Fdiff_absrm,Fdiff_new;
  double **dFdy,*fac;
  int *Ap=NULL, *Ai=NULL;

  dFdy = jac->dfdy; /* Assign pointer to dfdy directly for easier notation. */
  fac = jac->jacvec;
  if (jac->use_sparse){
    Ap = jac->spJ->Ap;
    Ai = jac->spJ->Ai;
  }

  /* Set new_jacobian flag: */
  jac->new_jacobian = _TRUE_;

  for(j=1;j<=neq;j++){
    nj_ws->yscale[j] = MAX(fabs(y[j]),thresh);
    nj_ws->del[j] = (y[j] + fac[j] * nj_ws->yscale[j]) - y[j];
  }

  /*Select an increment del for a difference approximation to
    column j of dFdy.  The vector fac accounts for experience
    gained in previous calls to numjac.
  */
  for(j=1;j<=neq;j++){
    if (nj_ws->del[j]==0.0){
      for(;;){
	if (fac[j] < facmax){
	  fac[j] = MIN(100*fac[j],facmax);
	  nj_ws->del[j] = (y[j] + fac[j]*nj_ws->yscale[j]) - y[j];
	  if(nj_ws->del[j]==0.0){
	    break;
	  }
	}
	else{
	  nj_ws->del[j] = thresh;
	  break;
	}
      }
    }
  }

  /* keep del pointing into region: */
  for(j=1;j<=neq;j++){
    if (fval[j]>=0.0){
      nj_ws->del[j] = fabs(nj_ws->del[j]);
    }
    else{
      nj_ws->del[j] = -fabs(nj_ws->del[j]);
    }
  }

  /* Sparse calculation?*/
  if ((jac->use_sparse)&&(jac->repeated_pattern >= jac->trust_sparse)){
    /* printf("\n Sparse calculation..neq=%d, has grouping=%d",neq,jac->has_grouping);*/
    /* Everything done sparse'ly. Do we have a grouping? */
    if (jac->has_grouping==0){
      jac->max_group = column_grouping(jac->spJ,jac->col_group,jac->col_wi);
      jac->has_grouping = 1;
    }
    colmax = jac->max_group+1;
    /*	printf("\n				->groups=%d/%d.",colmax,neq);  */
    for(j=1;j<=colmax;j++){
      /*loop over groups */
      group = j-1;
      for(i=1;i<=neq;i++){
	/*Add y-vector.. */
	nj_ws->ydel_Fdel[i][j] = y[i];
	/*Add del of all groupmembers:*/
	if(jac->col_group[i-1]==group) nj_ws->ydel_Fdel[i][j] +=nj_ws->del[i];
      }
    }
  }
  else{
    /*printf("\n Normal calculation..."); */
    /*Normal calculation: */
    colmax = neq;
    for(j=1;j<=neq;j++){
      for(i=1;i<=neq;i++){
	nj_ws->ydel_Fdel[i][j] = y[i];
      }
      nj_ws->ydel_Fdel[j][j] += nj_ws->del[j];
    }
  }

  /* The next section should work regardless of sparse...*/
  /* Evaluate the function at y+delta vectors:*/
  for(j=1;j<=colmax;j++){
    for(i=1;i<=neq;i++){
      nj_ws->yydel[i] = nj_ws->ydel_Fdel[i][j];
    }
    class_call((*derivs)(t,nj_ws->yydel+1,nj_ws->ffdel+1,
			 parameters_and_workspace_for_derivs,error_message),
	       error_message,error_message);

    *nfe+=1;
    for(i=1;i<=neq;i++) nj_ws->ydel_Fdel[i][j] = nj_ws->ffdel[i];
  }


  /*Using the Fdel array, form the jacobian and construct max-value arrays.
    First we do it for the sparse case, then for the normal case:*/
  if ((jac->use_sparse)&&(jac->repeated_pattern >= jac->trust_sparse)){
    /* Sparse case:*/
    for(j=0;j<neq;j++){
      /*Loop over columns, and assign corresponding group:*/
      group = jac->col_group[j];
      Fdiff_new = 0.0;
      Fdiff_absrm = 0.0;
      for(i=Ap[j];i<Ap[j+1];i++){
	/* Loop over rows in the sparse matrix */
	row = Ai[i]+1;
	/* Do I want to construct the full jacobian? No, that is ugly..*/
	Fdiff_absrm = MAX(Fdiff_absrm,fabs(Fdiff_new));
	Fdiff_new = nj_ws->ydel_Fdel[row][group+1]-fval[row]; /*Remember to access the column of the corresponding group */
	if (fabs(Fdiff_new)>=Fdiff_absrm){
	  nj_ws->Rowmax[j+1] = row;
	  nj_ws->Difmax[j+1] = Fdiff_new;
	}
	/* Assign value to sparse rep of jacobian: */
	jac->xjac[i] = Fdiff_new/nj_ws->del[j+1];
      }
      /* The maximum numerical value of Fdel in true column j+1*/
      nj_ws->absFdelRm[j+1] = fabs(nj_ws->ydel_Fdel[nj_ws->Rowmax[j+1]][group+1]);
    }
  }
  else{
    /*Normal case:*/
    for(j=1;j<=neq;j++){
      Fdiff_new = 0.0;
      Fdiff_absrm = 0.0;
      for(i=1;i<=neq;i++){
	Fdiff_absrm = MAX(fabs(Fdiff_new),Fdiff_absrm);
	Fdiff_new = nj_ws->ydel_Fdel[i][j] - fval[i];
	dFdy[i][j] = Fdiff_new/nj_ws->del[j];
	/*Find row maximums:*/
	if(fabs(Fdiff_new)>=Fdiff_absrm){
	  /* Found new max location in column */
	  nj_ws->Rowmax[j] = i;
	  nj_ws->Difmax[j] = fabs(Fdiff_new);
	}
      }
      nj_ws->absFdelRm[j] = fabs(nj_ws->ydel_Fdel[nj_ws->Rowmax[j]][j]);
    }
  }

  /* Adjust fac for next call to numjac. */
  for(i=1;i<=neq;i++){
    nj_ws->absFvalue[i] = fabs(fval[i]);
  }
  for(j=1;j<=neq;j++){
    nj_ws->absFvalueRm[j] = nj_ws->absFvalue[nj_ws->Rowmax[j]];
  }

  logjpos = 0;
  for(j=1;j<=neq;j++){
    if (((nj_ws->absFdelRm[j]<TINY)&&(nj_ws->absFvalueRm[j] < TINY))||(fabs(nj_ws->Difmax[j])<TINY)){
      nj_ws->logj[j] = 1;/*.true.*/
      logjpos = 1;
    }
    else{
      nj_ws->logj[j] = 0;
    }
  }

  if (logjpos ==1){
    for(i=1;i<=neq;i++){
      nj_ws->yydel[i] = y[i];
      nj_ws->Fscale[i] = MAX(nj_ws->absFdelRm[i],nj_ws->absFvalueRm[i]);
    }
    /* If the difference in f values is so small that the column might be just
       ! roundoff error, try a bigger increment. */
    for(j=1;j<=neq;j++){
      if ((nj_ws->logj[j]==1)&&(nj_ws->Difmax[j]<=(br*nj_ws->Fscale[j]))){
	tmpfac = MIN(sqrt(fac[j]),facmax);
	del2 = (y[j] + tmpfac*nj_ws->yscale[j]) - y[j];
	if ((tmpfac!=fac[j])&&(del2!=0.0)){
	  if (fval[j] >= 0.0){
	    /*! keep del pointing into region */
	    del2 = fabs(del2);
	  }
	  else{
	    del2 = -fabs(del2);
	  }
	  nj_ws->yydel[j] = y[j] + del2;
	  class_call((*derivs)(t,nj_ws->yydel+1,nj_ws->ffdel+1,
			       parameters_and_workspace_for_derivs,error_message),
		     error_message,error_message);
	  *nfe+=1;
	  nj_ws->yydel[j] = y[j];
	  rowmax2 = 1;
	  Fdiff_new=0.0;
	  Fdiff_absrm = 0.0;
	  for(i=1;i<=neq;i++){
	    Fdiff_absrm = MAX(Fdiff_absrm,fabs(Fdiff_new));
	    Fdiff_new = nj_ws->ffdel[i]-fval[i];
	    nj_ws->tmp[i] = Fdiff_new/del2;
	    if(fabs(Fdiff_new)>=Fdiff_absrm){
	      rowmax2 = i;
	      difmax2 = fabs(Fdiff_new);
	    }
	  }
	  maxval1 = difmax2*fabs(del2)*tmpfac;
	  maxval2 = nj_ws->Difmax[j]*fabs(nj_ws->del[j]);
	  if(maxval1>=maxval2){
	    /* The new difference is more significant, so
	       use the column computed with this increment.
	       This depends on wether we are in sparse mode or not: */
	    if ((jac->use_sparse)&&(jac->repeated_pattern >= jac->trust_sparse)){
	      for(i=Ap[j-1];i<Ap[j];i++) jac->xjac[i]=nj_ws->tmp[Ai[i]+1];
	    }
	    else{
	      for(i=1;i<=neq;i++) dFdy[i][j]=nj_ws->tmp[i];
	    }
	    /* Adjust fac for the next call to numjac. */
	    ffscale = MAX(fabs(nj_ws->ffdel[rowmax2]),nj_ws->absFvalue[rowmax2]);
	    if (difmax2 <= bl*ffscale){
	      /* The difference is small, so increase the increment. */
	      fac[j] = MIN(10*tmpfac, facmax);
	    }
	    else if(difmax2 > bu*ffscale){
	      /* The difference is large, so reduce the increment. */
	      fac[j] = MAX(0.1*tmpfac, facmin);
	    }
	    else{
	      fac[j] = tmpfac;
	    }
	  }
	}
      }
    }
  }
  /* If use_sparse is true but I still don't trust the sparsity pattern, go through the full calculated jacobi-
     matrix, deduce the sparsity pattern, compare with the old pattern, and write the new sparse Jacobi matrix.
     If I do this cleverly, I only have to walk through the jacobian once, and I don't need any local storage.*/

  if ((jac->use_sparse)&&(jac->repeated_pattern < jac->trust_sparse)){
    nz=0; /*Number of non-zeros */
    Ap[0]=0; /*<-Always is.. */
    pattern_broken = _FALSE_;
    for(j=1;j<=neq;j++){
      for(i=1;i<=neq;i++){
	if ((i==j)||(fabs(dFdy[i][j])!=0.0)){
	  /* Diagonal or non-zero index found. */
	  if (nz>=jac->max_nonzero){
	    /* Too many non-zero points to take advantage of sparsity.*/
	    jac->use_sparse = 0;
	    break;
	  }
	  /* Test pattern if it is still unbroken: */
	  /* Two conditions must be met if the pattern is intact: Ap[j-1]<=nz<Ap[j],
	     so that we are in the right column, and (i-1) must exist in column. Ai[nz]*/
	  /* We should first test if nz is in the column, otherwise pattern is dead:*/
	  if ((pattern_broken==_FALSE_)&&(jac->has_pattern==_TRUE_)){
	    if ((nz<Ap[j-1])||(nz>=Ap[j])){
	      /* If we are no longer in the right column, pattern is broken for sure. */
	      pattern_broken = _TRUE_;
	    }
	  }
	  if ((pattern_broken==_FALSE_)&&(jac->has_pattern==_TRUE_)){
	    /* Up to this point, the new jacobian has managed to fit in the old
	       sparsity pattern..*/
	    if (Ai[nz]!=(i-1)){
	      /* The current non-zero rownumber does not fit the current entry in the
		 sparse matrix. Pattern MIGHT be broken. Scan ahead in the sparse matrix
		 to search for the row entry: (Remember: the indices are sorted..)*/
	      pattern_broken = _TRUE_;
	      for(nz2=nz; (nz2<Ap[j])&&(Ai[nz2]<=(i-1)); nz2++){
		/* Go through the rest of the column with the added constraint that
		   the row index in the sparse matrix should be smaller than the current
		   row index i-1:*/
		if (Ai[nz2]==(i-1)){
		  /* sparsity pattern recovered.. */
		  pattern_broken = _FALSE_;
		  nz = nz2;
		  break;
		}
		/* Write a zero entry in the sparse matrix, in case we recover pattern. */
		jac->xjac[nz2] = 0.0;
	      }
	    }
	  }
	  /* The following works no matter the status of the pattern: */
	  /* Write row_number: */
	  Ai[nz] = i-1;
	  /* Write value: */
	  jac->xjac[nz] = dFdy[i][j];
	  nz++;
	}
      }
      /* Break this loop too if I have hit max non-zero points: */
      if (jac->use_sparse==_FALSE_) break;
      Ap[j]=nz;
    }
    if (jac->use_sparse==_TRUE_){
      if ((jac->has_pattern==_TRUE_)&&(pattern_broken==_FALSE_)){
	/*New jacobian fitted into the current sparsity pattern:*/
	jac->repeated_pattern++;
	/* printf("\n Found repeated pattern. nz=%d/%d and
	   rep.pat=%d.",nz,neq*neq,jac->repeated_pattern); */
      }
      else{
	/*Something has changed (or first run), better still do the full calculation..*/
	jac->repeated_pattern = 0;
      }
      jac->has_pattern = 1;
    }
  }
  return _SUCCESS_;
} /* End of numjac */
Exemplo n.º 7
0
int fzero_Newton(int (*func)(double *x,
                             int x_size,
                             void *param,
                             double *F,
                             ErrorMsg error_message),
                 double *x_inout,
                 double *dxdF,
                 int x_size,
                 double tolx,
                 double tolF,
                 void *param,
                 int *fevals,
                 ErrorMsg error_message){
  /**Given an initial guess x[1..n] for a root in n dimensions,
     take ntrial Newton-Raphson steps to improve the root.
     Stop if the root converges in either summed absolute
     variable increments tolx or summed absolute function values tolf.*/
  int k,i,j,*indx, ntrial=20;
  double errx,errf,d,*F0,*Fdel,**Fjac,*p, *lu_work;
  int has_converged = _FALSE_;
  double toljac = 1e-3;
  double *delx;

  /** All arrays are indexed as [0, n-1] with the exception of p, indx,
      lu_work and Fjac, since they are passed to ludcmp and lubksb. */
  class_alloc(indx, sizeof(int)*(x_size+1), error_message);
  class_alloc(p, sizeof(double)*(x_size+1), error_message);
  class_alloc(lu_work, sizeof(double)*(x_size+1), error_message);
  class_alloc(Fjac, sizeof(double *)*(x_size+1), error_message);
  Fjac[0] = NULL;
  class_alloc(Fjac[1], sizeof(double)*(x_size*x_size+1), error_message);
  for (i=2; i<=x_size; i++){
    Fjac[i] = Fjac[i-1] + x_size;
  }

  class_alloc(F0, sizeof(double)*x_size, error_message);
  class_alloc(delx, sizeof(double)*x_size, error_message);
  class_alloc(Fdel, sizeof(double)*x_size, error_message);

  for (i=1; i<=x_size; i++){
    delx[i-1] = toljac*dxdF[i-1];
  }

  for (k=1;k<=ntrial;k++) {
    /** Compute F(x): */
    /**printf("x = [%f, %f], delx = [%e, %e]\n",
       x_inout[0],x_inout[1],delx[0],delx[1]);*/
    class_call(func(x_inout, x_size, param, F0, error_message),
               error_message, error_message);
    /**    printf("F0 = [%f, %f]\n",F0[0],F0[1]);*/
    *fevals = *fevals + 1;
    errf=0.0; //fvec and Jacobian matrix in fjac.
    for (i=1; i<=x_size; i++)
      errf += fabs(F0[i-1]); //Check function convergence.
    if (errf <= tolF){
      has_converged = _TRUE_;
      break;
    }

    /**
    if (k==1){
      for (i=1; i<=x_size; i++){
        delx[i-1] *= F0[i-1];
      }
    }
    */

    /** Compute the jacobian of F: */
    for (i=1; i<=x_size; i++){
      if (F0[i-1]<0.0)
        delx[i-1] *= -1;
      x_inout[i-1] += delx[i-1];

      /**      printf("x = [%f, %f], delx = [%e, %e]\n",
               x_inout[0],x_inout[1],delx[0],delx[1]);*/
      class_call(func(x_inout, x_size, param, Fdel, error_message),
                 error_message, error_message);
      /**      printf("F = [%f, %f]\n",Fdel[0],Fdel[1]);*/
      for (j=1; j<=x_size; j++)
        Fjac[j][i] = (Fdel[j-1]-F0[j-1])/delx[i-1];
      x_inout[i-1] -= delx[i-1];
    }
    *fevals = *fevals + x_size;

    for (i=1; i<=x_size; i++)
      p[i] = -F0[i-1]; //Right-hand side of linear equations.
    ludcmp(Fjac, x_size, indx, &d, lu_work); //Solve linear equations using LU decomposition.
    lubksb(Fjac, x_size, indx, p);
    errx=0.0; //Check root convergence.
    for (i=1; i<=x_size; i++) { //Update solution.
      errx += fabs(p[i]);
      x_inout[i-1] += p[i];
    }
    if (errx <= tolx){
      has_converged = _TRUE_;
      break;
    }
  }

  free(p);
  free(lu_work);
  free(indx);
  free(Fjac[1]);
  free(Fjac);
  free(F0);
  free(delx);
  free(Fdel);

  if (has_converged == _TRUE_){
    return _SUCCESS_;
  }
  else{
    class_stop(error_message, "Newton's method failed to converge. Try improving initial guess on the parameters, decrease the tolerance requirements to Newtons method or increase the precision of the input function.\n");
  }
}