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(); }
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); } }
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(); }
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(); }
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(); }
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); }
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(); }
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(); }
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; }
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(); }
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; }
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(); }