示例#1
0
void ContinuationSystem::advance_arcstep()
{
  // Solve for the updated tangent du1/ds, d(lambda1)/ds
  solve_tangent();

  // Advance the solution and the parameter to the next value.
  update_solution();
}
示例#2
0
      void BaseView<Scalar>::on_special_key(int key, int x, int y)
      {
        switch (key)
        {
        case GLUT_KEY_LEFT:
          if(base_index > -1) base_index--;
          update_solution();
          break;

        case GLUT_KEY_RIGHT:
          if(base_index < ndof-1) base_index++;
          update_solution();
          break;

        default:
          ScalarView::on_special_key(key, x, y);
        }
      }
示例#3
0
void VectorBaseView::show(Space* space)
{
  free();
  pss = new PrecalcShapeset(space->get_shapeset());
  sln = new Solution();
  this->space = space;
  ndof = space->get_num_dofs();
  base_index = 0;
  update_solution();
}
示例#4
0
 void VectorBaseView<Scalar>::show(SpaceSharedPtr<Scalar> space)
 {
   free();
   pss = new PrecalcShapeset(space->shapeset);
   sln = new Solution<Scalar>();
   this->space = space;
   ndof = space->get_num_dofs();
   base_index = 0;
   update_solution();
 }
示例#5
0
 void BaseView<Scalar>::show(SpaceSharedPtr<Scalar> space, double eps, int item)
 {
   this->space = space;
   free();
   pss = new PrecalcShapeset(space->shapeset);
   ndof = this->space->get_num_dofs();
   base_index = 0;
   this->eps = eps;
   this->item = item;
   update_solution();
 }
示例#6
0
文件: stuff.c 项目: mokolodi1/bsq
t_solution		*make_solution(t_board *board)
{
	t_solution	*new_sol;

	new_sol = malloc(sizeof(t_solution));
	if (!new_sol)
		exit(ft_puterror("make_solution()", "Not Enough Memory"));
	new_sol->size = -1;
	update_solution(new_sol, 0, 0, board);
	return (new_sol);
}
示例#7
0
void BaseView::show(Space* space, double eps, int item)
{
  free();
  // todo: copy space
  pss = new PrecalcShapeset(space->get_shapeset());
  sln = new Solution();
  ndofs = space->get_num_dofs();
  base_index = 0;
  this->space = space;
  this->eps = eps;
  this->item = item;
  update_solution();
}
示例#8
0
 void BaseView<Scalar>::show(const Space<Scalar>* space, double eps, int item)
 {
   free();
   int order_increase = 0;
   this->space = space->dup(space->get_mesh(), order_increase);
   pss = new PrecalcShapeset(this->space->shapeset);
   sln = new Solution<Scalar>();
   ndof = this->space->get_num_dofs();
   base_index = 0;
   this->eps = eps;
   this->item = item;
   update_solution();
 }
示例#9
0
int newton_solver(double** x, void* con_ptr) {

  int iter=0;
  /*int iunk, ibox;*/
  int converged=FALSE, converged2=TRUE;
  char filename[FILENAME_LENGTH]="./matrix.dat";
  double start_t;
  double** delta_x,resid_sum;

  if (Type_poly==WJDC3 && Grafted_Logical==TRUE) 
       delta_x = (double **) array_alloc(2, Nunk_per_node, Nnodes_box_extra, sizeof(double));
  else delta_x = (double **) array_alloc(2, Nunk_per_node, Nnodes_box, sizeof(double));

  do {
    iter++;

    (void) dft_linprobmgr_initializeproblemvalues(LinProbMgr_manager);

    /* Call Matrix and Residual Fill routine, resid_only_flag=FALSE)*/
    start_t=MPI_Wtime();
    resid_sum=fill_resid_and_matrix_control(x, iter,FALSE); 
    if (iter==1) Time_fill_first=MPI_Wtime()-start_t;
    else         Time_fill_av+=(MPI_Wtime()-start_t);
    /*fill_test(x, FALSE);*/

    start_t=MPI_Wtime();
    (void) dft_linprobmgr_finalizeproblemvalues(LinProbMgr_manager);
    if (Iwrite_screen != SCREEN_NONE) print_resid_norm(iter);
    (void) dft_linprobmgr_setupsolver(LinProbMgr_manager);
    if (iter==1) Time_manager_first=MPI_Wtime()-start_t;
    else         Time_manager_av+=(MPI_Wtime()-start_t);

/*#ifdef NUMERICAL_JACOBIAN*/
/*   if (Iwrite_files==FILES_DEBUG_MATRIX) */  /*do_numerical_jacobian(x);*/
/*#endif*/
    start_t=MPI_Wtime();
    (void) dft_linprobmgr_solve(LinProbMgr_manager);
    if (iter==1) Time_linsolver_first=MPI_Wtime()-start_t;
    else         Time_linsolver_av+=(MPI_Wtime()-start_t);
    
    /* I am assuming getLhs returns box coordinates (e.g. Column Map)!! */
    (void) dft_linprobmgr_getlhs(LinProbMgr_manager, delta_x);

/*      for (iunk=0; iunk<Nunk_per_node; iunk++)
      for (ibox=0; ibox<Nnodes_box; ibox++) {
      printf("delta_x[%d][%d] = %g\n", iunk, ibox,delta_x[iunk][ibox]);
      }
  dft_linprobmgr_writeMatrix(LinProbMgr_manager,filename,NULL,NULL);*/
    
    if (con_ptr != NULL) converged2 =
      continuation_hook_conwrap(x, delta_x, con_ptr, NL_rel_tol, NL_abs_tol);

    /* Do: x += delta_x, and check for convergence */
    converged = update_solution(x, delta_x, iter);
    if (converged) fix_symmetries(x);

  } while (iter < Max_NL_iter && (!converged || !converged2));

  if (!converged || !converged2) {
    if (Proc==0 && Iwrite_screen!=SCREEN_NONE) printf("\tNewton Solver: Failed to converge in %d iterations\n",iter);
    iter = -iter;
  }
  else
    if (Proc==0 && Iwrite_screen!=SCREEN_NONE) printf("\tNewton Solver: Successful convergence in %d iterations\n",iter);

  safe_free((void **) &delta_x);
  return iter;
}
示例#10
0
    void CG::solve_lp(double epsilon){
        bool no_delete = valid_solution();
        if (no_delete) { // if there is no need to delete nodes
            cout << "CG::solve_lp() no need to delete nodes" << endl;
            return;
        }
        cout << "problem size: " << n_vertex_ << endl;
        double max_weight = 0;
        for (int ii = 0; ii < n_vertex_; ii++) {
            if (g_[ii].weight > max_weight) {
                max_weight = g_[ii].weight;
            }
        }
        // find the initial solution, which is the longest path in terms of the weights assigned
        for (int ii = 0; ii < n_vertex_; ii++) {
            g_[ii].dual_val = 1 + max_weight - g_[ii].weight;
        }
        double dummy1;
        vector<int> initial_path;
        find_shortest_path(dummy1, initial_path);
        for (vector<int>::iterator iter1 = initial_path.begin(); iter1 != initial_path.end(); ++iter1) {
            g_[*iter1].total_flow = 1;
        }
        
        double lambda = compute_lambda();
        double alpha = (4 / (lambda * epsilon)) * log(2 * n_vertex_ / epsilon);
        double delta = epsilon / (4 * alpha);

        double crt_left = 0.0;
        double crt_lambda = lambda;
        int iteration = -1;

        while (true) {
            iteration++;
            compute_dual_vals(alpha);

            double middle = 0; // middle corresponds to \vec{z}^tA\vec{y}
            for (int ii = 0; ii < n_vertex_; ii++) {
                middle = middle + g_[ii].dual_val * g_[ii].total_flow;
            }
            
            double right = 0; // right corresponds to \lambda\vec{z}^t\vec{b}
            for (int ii = 0; ii < n_vertex_; ii++) {
                right = right + crt_lambda * g_[ii].dual_val * g_[ii].weight;
            }
            
            vector<int> opt_path;
            double left; // left corresponds to \vec{z}^tA\vec{y}
            find_shortest_path(left, opt_path);
            crt_left = left;
            
            if (iteration % 1000 == 0) {
                cout << "iteration " << iteration 
                     << "  left:" << left 
                     << "  middle:" << middle 
                     << "  right:" << right
                     << "  sol:" << 1 / crt_lambda 
                     << endl;
            }

            // check if the following condition is met or not
            // \vec{z}^tA\vec{y} - C(\vec{z}) \le \epsilon(\vec{z}^tA\vec{y} + \lambda\vec{z}^t\vec{b})
            if ((middle - left) < epsilon * (middle + right) ) {
                cout << "converged!" << endl;
                cout << "iteration " << iteration 
                     << "  left:" << left 
                     << "  middle:" << middle 
                     << "  right:" << right
                     << "  sol:" << 1 / crt_lambda 
                     << endl;
                break;
            } else {
                update_solution(delta, opt_path);
                crt_lambda = compute_lambda();
                if (crt_lambda < 0.5 * lambda) {
                    lambda = crt_lambda;
                    alpha = 4 / (lambda * epsilon) * log(2 * n_vertex_ / epsilon);
                    delta = epsilon / (4 * alpha);
                }
            }
        }
        
        // compute the normalized dual solution
        for (int ii = 0; ii < n_vertex_; ii++) {
            g_[ii].nor_dual_val = g_[ii].dual_val / crt_left;
            if (g_[ii].nor_dual_val > 1) {
                g_[ii].nor_dual_val = 1;            
            }
        }
        // as the last step, round the fractional solution to integral solutions
        round_lp();    
    }
示例#11
0
文件: parheat.c 项目: dawuweijun/otpo
int main( int argc, char *argv[] )
{
    /* loop counters                */
    int i, j,n;

    /* time variables               */
    double starttime, all_starttime, all_ps_time_l, all_ps_time_g, endtime;
    double delta_t, delta_x;
    struct timing data = { 0, 0, 0, 0, 0, 0 };
    
    /* error variable               */
    int ierr;
    
    /* iteration counter            */
    int max_iter, num_iter;

    /* variables for the input file */
    int **grid;
    int mem_fac, msg_fac, cpt_fac;
    double accuracy, tstep_fac, c_fact;
    double min[3], max[3];
    
    /* variables needed for setting */
    /* up the correct topology      */
    int numprocs, myid, oldmyid, ndim, dimlist[3];
    int reorder, periods[3], coords[3], tcoords[3];
/* MIR */
    int ncoords[3];
/* MIR */
    MPI_Comm newcomm;
    int nodenum;
    
    /* variables for the pack/unpack */
    /* routines                      */
    int position, numvars, buffsize;
    
    /* variables for the get_domain  */
    /* routine                       */
    int ppnode[3];
    double lmin[3], lmax[3]; 
    
    /* variables for get_mesh_mem    */
    struct point **setlist;
    
    /* variable for get_time_mem     */
    struct tstep solution;
    
    /* array for the neighbor process ranks */
    int neighbor[6];
    
    /* variables to account for the modified */
    /* domain.                               */
    int start[3], end[3];
    int num_bfaces, num_ifaces;
    int num_bcnodes, max_bcnodes;
    int *bcnode = NULL;
    int nb_of_problems;
    /* Filename for output file      */
    char filename[]="parheat.dat";
    
    /* this is necessary for getting the timing */
    /* information to the root process          */
    double tsend[6] = { 0, 0, 0, 0, 0, 0 };
    double *trecv;
    
    for( i=0 ; i<6 ; i++ ) 
    {
	neighbor[i] = MPI_PROC_NULL;
    }    
    if( ierr=MPI_Init( &argc, &argv ) != 0 )
    {
	printf( "MPI_Init failed with code %d.\n", ierr );
	exit( ierr );
    }
    ADCL_Init();
    MPI_Comm_size( MPI_COMM_WORLD, &numprocs );
    MPI_Comm_rank( MPI_COMM_WORLD, &oldmyid );
    
    get_dimlist( numprocs, &ndim, dimlist );
    
    periods[0] = 0;
    periods[1] = 0;
    periods[2] = 0;
    reorder = 1;
    
    /* take care of unused dimensions */
    for( i=0 ; i<3 ; i++ ) {
        coords[i] = 0;
    }
    if( ierr=MPI_Cart_create( MPI_COMM_WORLD, ndim, dimlist, periods, 
			      reorder, &newcomm ) != 0 ) {
        printf( "MPI_Cart_create failed with code %d.\n", ierr );
        MPI_Abort ( MPI_COMM_WORLD, ierr );
    }
    
    MPI_Comm_rank( newcomm, &myid );
    MPI_Cart_coords( newcomm, myid, ndim, coords );
    
    if( myid == 0  ) {
	printf( "There are %d processes.\n", numprocs );
    }
    
    if ( 0 > read_input( &nb_of_problems, &grid, &mem_fac, &msg_fac, &cpt_fac, \
                         &accuracy, &tstep_fac, &c_fact, min, max, &max_iter  ) ) {
        printf("Error in memory allocation\n");
        return 0;
    }

    /* Start time for solving all pb sizes */
    for( i=0 ; i<ndim ; i++ ) {
        if( ierr = MPI_Cart_shift( newcomm, i, 1, &neighbor[i], &neighbor[i+3] ) != 0 ) {
            printf( "MPI_Cart_shift failed with code %d.\n" , ierr );
            MPI_Abort ( MPI_COMM_WORLD, ierr );
        }
    }
    all_starttime = MPI_Wtime();
    /* Looping for all problem sizes */
    for ( n=0; n<nb_of_problems; n++ ) {
        /* Start time for solving the current pb size */
        starttime = MPI_Wtime();
        /* MIR */
        delta_x = 1.0/(grid[n][1]-1);
        delta_t = tstep_fac * delta_x *delta_x/6.0;
        /* MIR */

        if( get_domain( grid[n], coords, dimlist, ndim,		\
                        min, max, ppnode, lmin, lmax ) != 0 ) {
            printf( "Error in get_domain.\n" );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }

        /* find out the right properties for */
        /* my particular domain.             */
        num_bfaces = 0;
        num_ifaces = 0;
        for( i=0 ; i<3 ; i++ ) {
            if( neighbor[i] != MPI_PROC_NULL ) {
                ppnode[i]++;
                start[i] = 1;
                num_ifaces++;
            }
            else {
                start[i] = 0;
                num_bfaces++;
            }
            if( neighbor[i+3] != MPI_PROC_NULL ) {
                ppnode[i]++;
                end[i] = ppnode[i] - 2;
                num_ifaces++;
            }
            else {
                end[i] = ppnode[i] - 1;
                num_bfaces++;
            }
        }
        
        if( ierr=get_mesh_mem( mem_fac, ppnode, &setlist ) != 0 ) {
            printf( "process %d: get_mesh_mem failed with code %d.\n", 
		myid, ierr );
        }
        if( ierr=get_coords( ppnode, start, end,        \
            lmin, lmax, *setlist ) != 0 ) {
            printf( "parheat: get_coords failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
    
        if( ierr=get_time_mem( ppnode, &solution ) != 0 ) {
            printf( "parheat: get_time_mem failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
        /* compute the maximal possible number   */
        /* of boundary nodes.                    */
        max_bcnodes = 0;
        for( i=0 ; i<6 ; i++ ) {
            if( neighbor[i] == MPI_PROC_NULL ) {
                max_bcnodes += ppnode[ (i+1)%3 ] * ppnode[ (i+2)%3 ];
            }
        }
        if( NULL != bcnode ) {
            free(bcnode);
        }
        if( ierr=get_bcnode_mem( max_bcnodes, &bcnode ) != 0 ) {
            printf( "parheat: get_bcnode_mem failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
    
        if( ierr=find_bcnodes( ppnode, start, end, neighbor,	\
                               bcnode, &num_bcnodes ) != 0 ) {
            printf( "parheat: find_bcnodes failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
    
        if( ierr=set_initial( ppnode, solution.old ) != 0 ) {
            printf( "parheat: set_initial failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
    
        if( ierr=apply_bc( num_bcnodes, *setlist, solution.old,	\
                           bcnode ) != 0 ) {
            printf( "parheat: apply_bc failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
    
        if( ierr=apply_bc( num_bcnodes, *setlist, solution.neu,	\
                           bcnode ) != 0 ) {
            printf( "parheat: apply_bc failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, 1 );
        }
        /* Initialazation of data timing struct */
        data.comp = 0;
        data.comm_start = 0;
        data.recv_end = 0;
        data.send_end = 0;
        data.sync = 0;
        data.total = 0;
        /* Here comes the actual computation ! */
        if( ierr=update_solution( c_fact, delta_t, delta_x, ppnode,   
                                  start, end, neighbor, tstep_fac, accuracy,
                                  msg_fac, cpt_fac, max_iter, &num_iter,
                                  *setlist, &data, &solution, newcomm ) != 0 ) {
            printf( "update_ solution failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, ierr );
        }
   
        endtime = MPI_Wtime();
        data.total = endtime - starttime;
        tsend[0] = data.comp;
        tsend[1] = data.comm_start;
        tsend[2] = data.recv_end;
        tsend[3] = data.send_end;
        tsend[4] = data.sync;
        tsend[5] = data.total;

        if( myid == 0 ) {
            trecv = (double *)malloc( 6*numprocs*sizeof(double) );
        }
        if( ierr = MPI_Gather( (void *)&tsend, 6, MPI_DOUBLE, (void *)trecv, 6,
                               MPI_DOUBLE, 0, newcomm ) != 0 ) {
            printf( "MPI_Gather failed with code %d.\n", ierr );
            MPI_Abort ( MPI_COMM_WORLD, ierr );
        }

        if( myid == 0 ) {
            printf( "grid: %dx%dx%d\n", grid[n][0], grid[n][1], grid[n][2] );
            printf( "mem_fac=%d, msg_fac=%d, cpt_fac=%d\n", mem_fac, msg_fac, cpt_fac );
            printf( "accuracy=%le\n", accuracy );
            printf( "Number of iterations: %d.\n", num_iter );
            
            printf( "\ttime[sec]\t\tcomputation\tcomm_start  \trecv_end" );
            printf( "\tsend_end\tsync\ttotal\n" );
            for( i=0 ; i<numprocs*6 ; i+=6 ) {
                nodenum = i/6;
                MPI_Cart_coords( newcomm, nodenum, ndim, tcoords );
                
                printf( "node %4d coords=", nodenum );
                for( j=0 ; j<3 ; j++ ) {
                    printf( "%3d ", tcoords[j] );
                }
                printf( ":" );
                for( j=0 ; j<6 ; j++ ) {
                    printf( "\t%lf ", trecv[i+j] );
                }
                printf( "\n" );
            }
	
            if( ierr=write_step( ppnode, *setlist, solution.old, filename ) != 0 ) {
                printf( "process %d: write_step failed with code %d.\n", myid, ierr );
                MPI_Abort ( MPI_COMM_WORLD, 1 );
            }
        }
        /* Freeing allocated memory */
        for( i=0; i<mem_fac; i++ ) {
            free(setlist[i]);
        }
        free(setlist);
        free(solution.start);

    }
    /* End of the timer for solving all pb sizes */
    all_ps_time_l = MPI_Wtime() - all_starttime;
    MPI_Reduce ( &all_ps_time_l, &all_ps_time_g, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
    if( 0 == myid ) {
        printf("The overall execution time of all problem sizes is: %f\n", all_ps_time_g );
    }

    ADCL_Finalize();
    MPI_Finalize();
    return 0;
}
示例#12
0
void ContinuationSystem::initialize_tangent()
{
  // Be sure the tangent was not already initialized.
  libmesh_assert (!tangent_initialized);

  // Compute delta_s_zero, the initial arclength travelled during the
  // first step.  Here we assume that previous_u and lambda_old store
  // the previous solution and control parameter.  You may need to
  // read in an old solution (or solve the non-continuation system)
  // first and call save_current_solution() before getting here.

  // 1.) Compute delta_s_zero as ||u|| - ||u_old|| + ...
  // Compute norms of the current and previous solutions
//   Real norm_u          = solution->l2_norm();
//   Real norm_previous_u = previous_u->l2_norm();

//   if (!quiet)
//     {
//       libMesh::out << "norm_u=" << norm_u << std::endl;
//       libMesh::out << "norm_previous_u=" << norm_previous_u << std::endl;
//     }

//   if (norm_u == norm_previous_u)
//     {
//       libMesh::err << "Warning, it appears u and previous_u are the "
//   		<< "same, are you sure this is correct?"
//   		<< "It's possible you forgot to set one or the other..."
//   		<< std::endl;
//     }

//   Real delta_s_zero = std::sqrt(
//   				(norm_u - norm_previous_u)*(norm_u - norm_previous_u) +
//   				(*continuation_parameter-old_continuation_parameter)*
//   				(*continuation_parameter-old_continuation_parameter)
//   				);

//   // 2.) Compute delta_s_zero as ||u -u_old|| + ...
//   *delta_u = *solution;
//   delta_u->add(-1., *previous_u);
//   delta_u->close();
//   Real norm_delta_u = delta_u->l2_norm();
//   Real norm_u          = solution->l2_norm();
//   Real norm_previous_u = previous_u->l2_norm();

//   // Scale norm_delta_u by the bigger of either norm_u or norm_previous_u
//   norm_delta_u /= std::max(norm_u, norm_previous_u);

//   if (!quiet)
//     {
//       libMesh::out << "norm_u=" << norm_u << std::endl;
//       libMesh::out << "norm_previous_u=" << norm_previous_u << std::endl;
//       //libMesh::out << "norm_delta_u=" << norm_delta_u << std::endl;
//       libMesh::out << "norm_delta_u/max(|u|,|u_old|)=" << norm_delta_u << std::endl;
//       libMesh::out << "|norm_u-norm_previous_u|=" << std::abs(norm_u - norm_previous_u) << std::endl;
//     }

//   const Real dlambda = *continuation_parameter-old_continuation_parameter;

//   if (!quiet)
//     libMesh::out << "dlambda=" << dlambda << std::endl;

//   Real delta_s_zero = std::sqrt(
//   				(norm_delta_u*norm_delta_u) +
//   				(dlambda*dlambda)
//   				);

//   if (!quiet)
//     libMesh::out << "delta_s_zero=" << delta_s_zero << std::endl;

  // 1.) + 2.)
//   // Now approximate the initial tangent d(lambda)/ds
//   this->dlambda_ds = (*continuation_parameter-old_continuation_parameter) / delta_s_zero;


//   // We can also approximate the deriv. wrt s by finite differences:
//   // du/ds = (u1 - u0) / delta_s_zero.
//   // FIXME: Use delta_u from above if we decide to keep that method.
//   *du_ds = *solution;
//   du_ds->add(-1., *previous_u);
//   du_ds->scale(1./delta_s_zero);
//   du_ds->close();


  // 3.) Treating (u-previous_u)/(lambda - lambda_old) as an approximation to du/d(lambda),
  // we follow the same technique as Carnes and Shadid.
//   const Real dlambda = *continuation_parameter-old_continuation_parameter;
//   libmesh_assert_greater (dlambda, 0.);

//   // Use delta_u for temporary calculation of du/d(lambda)
//   *delta_u = *solution;
//   delta_u->add(-1., *previous_u);
//   delta_u->scale(1. / dlambda);
//   delta_u->close();

//   // Determine initial normalization parameter
//   const Real solution_size = std::max(solution->l2_norm(), previous_u->l2_norm());
//   if (solution_size > 1.)
//     {
//       Theta = 1./solution_size;

//       if (!quiet)
// 	libMesh::out << "Setting Normalization Parameter Theta=" << Theta << std::endl;
//     }

//   // Compute d(lambda)/ds
//   // The correct sign of d(lambda)/ds should be positive, since we assume that (lambda > lambda_old)
//   // but we could always double-check that as well.
//   Real norm_delta_u = delta_u->l2_norm();
//   this->dlambda_ds = 1. / std::sqrt(1. + Theta*Theta*norm_delta_u*norm_delta_u);

//   // Finally, compute du/ds = d(lambda)/ds * du/d(lambda)
//   *du_ds = *delta_u;
//   du_ds->scale(dlambda_ds);
//   du_ds->close();


  // 4.) Use normalized arclength formula to estimate delta_s_zero
//   // Determine initial normalization parameter
//   set_Theta();

//   // Compute (normalized) delta_s_zero
//   *delta_u = *solution;
//   delta_u->add(-1., *previous_u);
//   delta_u->close();
//   Real norm_delta_u = delta_u->l2_norm();

//   const Real dlambda = *continuation_parameter-old_continuation_parameter;

//   if (!quiet)
//     libMesh::out << "dlambda=" << dlambda << std::endl;

//   Real delta_s_zero = std::sqrt(
//   				(Theta_LOCA*Theta_LOCA*Theta*norm_delta_u*norm_delta_u) +
//   				(dlambda*dlambda)
//   				);
//   *du_ds = *delta_u;
//   du_ds->scale(1./delta_s_zero);
//   dlambda_ds = dlambda / delta_s_zero;

//   if (!quiet)
//     {
//       libMesh::out << "delta_s_zero=" << delta_s_zero << std::endl;
//       libMesh::out << "initial d(lambda)/ds|_0 = " << dlambda_ds << std::endl;
//       libMesh::out << "initial ||du_ds||_0 = " << du_ds->l2_norm() << std::endl;
//     }

//   // FIXME: Also store the initial finite-differenced approximation to -du/dlambda as y.
//   // We stick to the convention of storing negative y, since that is what we typically
//   // solve for anyway.
//   *y = *delta_u;
//   y->scale(-1./dlambda);
//   y->close();



  // 5.) Assume dlambda/ds_0 ~ 1/sqrt(2) and determine the value of Theta_LOCA which
  // will satisfy this criterion

  // Initial change in parameter
  const Real dlambda = *continuation_parameter-old_continuation_parameter;
  libmesh_assert_not_equal_to (dlambda, 0.0);

  // Ideal initial value of dlambda_ds
  dlambda_ds = 1. / std::sqrt(2.);
  if (dlambda < 0.)
    dlambda_ds *= -1.;

  // This also implies the initial value of ds
  ds_current = dlambda / dlambda_ds;

  if (!quiet)
    libMesh::out << "Setting ds_current|_0=" << ds_current << std::endl;

  // Set y = -du/dlambda using finite difference approximation
  *y = *solution;
  y->add(-1., *previous_u);
  y->scale(-1./dlambda);
  y->close();
  const Real ynorm=y->l2_norm();

  // Finally, set the value of du_ds to be used in the upcoming
  // tangent calculation. du/ds = du/dlambda * dlambda/ds
  *du_ds = *y;
  du_ds->scale(-dlambda_ds);
  du_ds->close();

  // Determine additional solution normalization parameter
  // (Since we just set du/ds, it will be:  ||du||*||du/ds||)
  set_Theta();

  // The value of Theta_LOCA which makes dlambda_ds = 1/sqrt(2),
  // assuming our Theta = ||du||^2.
  // Theta_LOCA = std::abs(dlambda);

  // Assuming general Theta
  Theta_LOCA = std::sqrt(1./Theta/ynorm/ynorm);


  if (!quiet)
    {
      libMesh::out << "Setting initial Theta_LOCA = " << Theta_LOCA << std::endl;
      libMesh::out << "Theta_LOCA^2*Theta         = " << Theta_LOCA*Theta_LOCA*Theta << std::endl;
      libMesh::out << "initial d(lambda)/ds|_0    = " << dlambda_ds << std::endl;
      libMesh::out << "initial ||du_ds||_0        = " << du_ds->l2_norm() << std::endl;
    }



  // OK, we estimated the tangent at point u0.
  // Now, to estimate the tangent at point u1, we call the solve_tangent routine.

  // Set the flag which tells us the method has been initialized.
  tangent_initialized = true;

  solve_tangent();

  // Advance the solution and the parameter to the next value.
  update_solution();
}