Пример #1
0
main(int argc, char* argv[]){
    static vec u(M+1), utp1(M+1), utp2(M+1);
    static vec sol(M+1);
	int k,n;
    std::string op=argv[1];
    init(u,sol);
	val dx=1.0/M, tn, dt=T/N, dx2=dx*dx, up, un;
    val r=NU*dt/dx2;    // r = nu*dt/dx^2
    for(n=1;n<=N;n++){
        utp2=u; // u^n-1
        tn=n*dt;
        u(0)=0.0;  // a(tn)
        for(k=1;k<M;k++){
           up=u(k-1);
           un=u(k+1);
           if(n==1) u(k)=exact_sol(k*dx,tn);
           else u(k)=utp1(k)+2*r*(un-2*u(k)+up); // u_k = 2*r*(u_k+1 - 2*u_k + u_k-1)
           sol(k)=exact_sol(k*dx,tn);
        }
        utp1=utp2;
        u(M)= 0.0;  // b(tn)
        output(tn, dx, u, sol, op);
    }
    return 0;
}
Пример #2
0
// Exact solution.
scalar3 exact(double x, double y, double z, scalar3 &dx, scalar3 &dy, scalar3 &dz)
{
  scalar3 ex(0.0, 0.0, 0.0);

  exact_sol(x, y, z, ex[0], ex[1], dx[1], dy[0]);
  return ex;
}
Пример #3
0
int run( char* argv[], GRINS::Runner & grins )
{
  grins.init();
  grins.run();

  GRINS::Simulation & sim = grins.get_simulation();

  // Get equation systems to create ExactSolution object
  std::shared_ptr<libMesh::EquationSystems>
    es = sim.get_equation_system();

  //es->write("foobar.xdr");

  // Create Exact solution object and attach exact solution quantities
  libMesh::ExactSolution exact_sol(*es);

  libMesh::EquationSystems es_ref( es->get_mesh() );

  // Filename of file where comparison solution is stashed
  std::string solution_file = std::string(argv[2]);
  es_ref.read( solution_file );

  exact_sol.attach_reference_solution( &es_ref );

  // Compute error and get it in various norms
  exact_sol.compute_error("StretchedElasticSheet", "u");
  exact_sol.compute_error("StretchedElasticSheet", "v");
  exact_sol.compute_error("StretchedElasticSheet", "w");

  double u_l2error = exact_sol.l2_error("StretchedElasticSheet", "u");
  double u_h1error = exact_sol.h1_error("StretchedElasticSheet", "u");

  double v_l2error = exact_sol.l2_error("StretchedElasticSheet", "v");
  double v_h1error = exact_sol.h1_error("StretchedElasticSheet", "v");

  double w_l2error = exact_sol.l2_error("StretchedElasticSheet", "w");
  double w_h1error = exact_sol.h1_error("StretchedElasticSheet", "w");

  int return_flag = 0;

  double tol = 5.0e-8;

  if( u_l2error > tol   || u_h1error > tol   ||
      v_l2error > tol   || v_h1error > tol   ||
      w_l2error > tol   || w_h1error > tol     )
    {
      return_flag = 1;

      std::cout << "Tolerance exceeded for thermally driven flow test." << std::endl
                << "tolerance     = " << tol << std::endl
                << "u l2 error    = " << u_l2error << std::endl
                << "u h1 error    = " << u_h1error << std::endl
                << "v l2 error    = " << v_l2error << std::endl
                << "v h1 error    = " << v_h1error << std::endl
                << "w l2 error    = " << w_l2error << std::endl
                << "w h1 error    = " << w_h1error << std::endl;
    }

  return return_flag;
}
Пример #4
0
// Exact solution.
scalar3 &exact(double x, double y, double z, scalar3 &dx, scalar3 &dy, scalar3 &dz)
{
  static scalar3 ex;

  ex[0] = ex[1] = ex[2] = 0;
  exact_sol(x, y, z, ex[0], ex[1], dx[1], dy[0]);
  return ex;
}
Пример #5
0
void init(vec &u, vec &sol){
    int k;
	val dx=1.0/M, xk;
	for(k=0;k<=M;k++){
        xk=k*dx;
        u(k)=f(xk);
        sol(k)=exact_sol(xk,0);
    }
}
Пример #6
0
scalar2 exact(double x, double y, scalar2& dx, scalar2& dy)
{
  static scalar2 ex(0.0, 0.0);
  exact_sol(x,y, ex[0], ex[1], dx[1], dy[0]);

  dx[0] = 0.0; // not important
  dy[1] = 0.0; // not important

  return ex;
}
int main(int argc, char* argv[]) 
{

#ifdef GRINS_USE_GRVY_TIMERS
  GRVY::GRVY_Timer_Class grvy_timer;
  grvy_timer.Init("GRINS Timer");
#endif

  // Check command line count.
  if( argc < 2 )
    {
      // TODO: Need more consistent error handling.
      std::cerr << "Error: Must specify libMesh input file." << std::endl;
      exit(1); // TODO: something more sophisticated for parallel runs?
    }

  // libMesh input file should be first argument
  std::string libMesh_input_filename = argv[1];
  
  // Create our GetPot object.
  GetPot libMesh_inputfile( libMesh_input_filename );

#ifdef GRINS_USE_GRVY_TIMERS
  grvy_timer.BeginTimer("Initialize Solver");
#endif

  // Initialize libMesh library.
  libMesh::LibMeshInit libmesh_init(argc, argv);
 
  GRINS::SimulationBuilder sim_builder;

  GRINS::SharedPtr<GRINS::BoundaryConditionsFactory> bc_factory( new ParabolicBCFactory );

  sim_builder.attach_bc_factory(bc_factory);

  GRINS::Simulation grins( libMesh_inputfile,
			   sim_builder,
                           libmesh_init.comm() );

#ifdef GRINS_USE_GRVY_TIMERS
  grvy_timer.EndTimer("Initialize Solver");

  // Attach GRVY timer to solver
  grins.attach_grvy_timer( &grvy_timer );
#endif

  // Solve
  grins.run();

  // Get equation systems to create ExactSolution object
  GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system();

  // Create Exact solution object and attach exact solution quantities
  libMesh::ExactSolution exact_sol(*es);

  exact_sol.attach_exact_value(&exact_solution);
  exact_sol.attach_exact_deriv(&exact_derivative);
  
  // Compute error and get it in various norms
  exact_sol.compute_error("GRINS", "u");

  double l2error = exact_sol.l2_error("GRINS", "u");
  double h1error = exact_sol.h1_error("GRINS", "u");

  int return_flag = 0;

  const double tol = 1.0e-8;

  if( l2error > tol || h1error > tol )
    {
      return_flag = 1;

      std::cout << "Tolerance exceeded for velocity in Poiseuille test." << std::endl
		<< "l2 error = " << l2error << std::endl
		<< "h1 error = " << h1error << std::endl;
    }

  // Compute error and get it in various norms
  exact_sol.compute_error("GRINS", "p");

  l2error = exact_sol.l2_error("GRINS", "p");
  h1error = exact_sol.h1_error("GRINS", "p");

  if( l2error > tol || h1error > tol )
    {
      return_flag = 1;

      std::cout << "Tolerance exceeded for pressure in Poiseuille test." << std::endl
		<< "l2 error = " << l2error << std::endl
		<< "h1 error = " << h1error << std::endl;
    }

  return return_flag;
}
Пример #8
0
int main(int argc, char* argv[])
{
#ifdef GRINS_USE_GRVY_TIMERS
    GRVY::GRVY_Timer_Class grvy_timer;
    grvy_timer.Init("GRINS Timer");
#endif

    // Check command line count.
    if( argc < 3 )
    {
        // TODO: Need more consistent error handling.
        std::cerr << "Error: Must specify libMesh input file and solution file." << std::endl;
        exit(1); // TODO: something more sophisticated for parallel runs?
    }

    // libMesh input file should be first argument
    std::string libMesh_input_filename = argv[1];

    // Create our GetPot object.
    GetPot libMesh_inputfile( libMesh_input_filename );

#ifdef GRINS_USE_GRVY_TIMERS
    grvy_timer.BeginTimer("Initialize Solver");
#endif

    // Initialize libMesh library.
    libMesh::LibMeshInit libmesh_init(argc, argv);

    GRINS::SimulationBuilder sim_builder;

    sim_builder.attach_bc_factory( GRINS::SharedPtr<GRINS::BoundaryConditionsFactory>( new GRINS::ThermallyDrivenFlowTestBCFactory( libMesh_inputfile ) ) );

    GRINS::Simulation grins( libMesh_inputfile,
                             sim_builder,
                             libmesh_init.comm() );

#ifdef GRINS_USE_GRVY_TIMERS
    grvy_timer.EndTimer("Initialize Solver");

    // Attach GRVY timer to solver
    grins.attach_grvy_timer( &grvy_timer );
#endif

    // Do solve here
    grins.run();

    // Get equation systems to create ExactSolution object
    GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system();

    //es->write("foobar.xdr");

    // Create Exact solution object and attach exact solution quantities
    libMesh::ExactSolution exact_sol(*es);

    libMesh::EquationSystems es_ref( es->get_mesh() );

    // Filename of file where comparison solution is stashed
    std::string solution_file = std::string(argv[2]);
    es_ref.read( solution_file );

    exact_sol.attach_reference_solution( &es_ref );

    // Compute error and get it in various norms
    exact_sol.compute_error("GRINS", "u");
    exact_sol.compute_error("GRINS", "v");

    if( (es->get_mesh()).mesh_dimension() == 3 )
        exact_sol.compute_error("GRINS", "w");

    exact_sol.compute_error("GRINS", "p");
    exact_sol.compute_error("GRINS", "T");

    double u_l2error = exact_sol.l2_error("GRINS", "u");
    double u_h1error = exact_sol.h1_error("GRINS", "u");

    double v_l2error = exact_sol.l2_error("GRINS", "v");
    double v_h1error = exact_sol.h1_error("GRINS", "v");

    double p_l2error = exact_sol.l2_error("GRINS", "p");
    double p_h1error = exact_sol.h1_error("GRINS", "p");

    double T_l2error = exact_sol.l2_error("GRINS", "T");
    double T_h1error = exact_sol.h1_error("GRINS", "T");

    double w_l2error = 0.0,
           w_h1error = 0.0;

    if( (es->get_mesh()).mesh_dimension() == 3 )
    {
        w_l2error = exact_sol.l2_error("GRINS", "w");
        w_h1error = exact_sol.h1_error("GRINS", "w");
    }

    int return_flag = 0;

    // This is the tolerance of the iterative linear solver so
    // it's unreasonable to expect anything better than this.
    double tol = 8.0e-9;

    if( u_l2error > tol || u_h1error > tol ||
            v_l2error > tol || v_h1error > tol ||
            w_l2error > tol || w_h1error > tol ||
            p_l2error > tol || p_h1error > tol ||
            T_l2error > tol || T_h1error > tol   )
    {
        return_flag = 1;

        std::cout << "Tolerance exceeded for thermally driven flow test." << std::endl
                  << "tolerance = " << tol << std::endl
                  << "u l2 error = " << u_l2error << std::endl
                  << "u h1 error = " << u_h1error << std::endl
                  << "v l2 error = " << v_l2error << std::endl
                  << "v h1 error = " << v_h1error << std::endl
                  << "w l2 error = " << w_l2error << std::endl
                  << "w h1 error = " << w_h1error << std::endl
                  << "p l2 error = " << p_l2error << std::endl
                  << "p h1 error = " << p_h1error << std::endl
                  << "T l2 error = " << T_l2error << std::endl
                  << "T h1 error = " << T_h1error << std::endl;
    }

    return return_flag;
}
int run( int argc, char* argv[], const GetPot& input )
{
  // Initialize libMesh library.
  libMesh::LibMeshInit libmesh_init(argc, argv);
 
  GRINS::SimulationBuilder sim_builder;

  std::tr1::shared_ptr<GRINS::BoundaryConditionsFactory> bc_factory( new NitridationCalibration::BoundaryConditionsFactory(input) );

  sim_builder.attach_bc_factory( bc_factory );

  std::tr1::shared_ptr<GRINS::QoIFactory> qoi_factory( new NitridationCalibration::QoIFactory );

  sim_builder.attach_qoi_factory( qoi_factory );

  GRINS::Simulation grins( input,
			   sim_builder,
                           libmesh_init.comm());

  //FIXME: We need to move this to within the Simulation object somehow...
  std::string restart_file = input( "restart-options/restart_file", "none" );

  std::tr1::shared_ptr<NitridationCalibration::TubeTempBC> wall_temp;
  
  std::string system_name = input( "screen-options/system_name", "GRINS" );

  if( restart_file == "none" )
    {
      // Asssign initial temperature value
      std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();
      const libMesh::System& system = es->get_system(system_name);
      
      libMesh::Parameters &params = es->parameters;

      libMesh::Real& w_N2 = params.set<libMesh::Real>( "w_N2" );
      w_N2 = input( "Physics/ReactingLowMachNavierStokes/bound_species_1", 0.0, 0 );
      
      libMesh::Real& w_N = params.set<libMesh::Real>( "w_N" );
      w_N = input( "Physics/ReactingLowMachNavierStokes/bound_species_1", 0.0, 1 );

      wall_temp.reset( new NitridationCalibration::TubeTempBC( input ) );
      std::tr1::shared_ptr<NitridationCalibration::TubeTempBC>& dummy = params.set<std::tr1::shared_ptr<NitridationCalibration::TubeTempBC> >( "wall_temp" );
      dummy = wall_temp;

      system.project_solution( initial_values, NULL, params );
    }

  grins.run();

  // Get equation systems to create ExactSolution object
  std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();

  //es->write("foobar.xdr");

  // Create Exact solution object and attach exact solution quantities
  libMesh::ExactSolution exact_sol(*es);
  
  libMesh::EquationSystems es_ref( es->get_mesh() );

  // Filename of file where comparison solution is stashed
  std::string solution_file = std::string(argv[2]);
  es_ref.read( solution_file );

  exact_sol.attach_reference_solution( &es_ref );
  
  // Compute error and get it in various norms
  exact_sol.compute_error(system_name, "u");
  exact_sol.compute_error(system_name, "v");

  if( (es->get_mesh()).mesh_dimension() == 3 )
    exact_sol.compute_error(system_name, "w");

  exact_sol.compute_error(system_name, "p");
  exact_sol.compute_error(system_name, "T");
  exact_sol.compute_error(system_name, "w_N2");
  exact_sol.compute_error(system_name, "w_N");
  exact_sol.compute_error(system_name, "w_CN");

  double u_l2error = exact_sol.l2_error(system_name, "u");
  double u_h1error = exact_sol.h1_error(system_name, "u");

  double v_l2error = exact_sol.l2_error(system_name, "v");
  double v_h1error = exact_sol.h1_error(system_name, "v");

  double p_l2error = exact_sol.l2_error(system_name, "p");
  double p_h1error = exact_sol.h1_error(system_name, "p");

  double T_l2error = exact_sol.l2_error(system_name, "T");
  double T_h1error = exact_sol.h1_error(system_name, "T");

  double wN_l2error = exact_sol.l2_error(system_name, "w_N");
  double wN_h1error = exact_sol.h1_error(system_name, "w_N");

  double wN2_l2error = exact_sol.l2_error(system_name, "w_N2");
  double wN2_h1error = exact_sol.h1_error(system_name, "w_N2");

  double wCN_l2error = exact_sol.l2_error(system_name, "w_CN");
  double wCN_h1error = exact_sol.h1_error(system_name, "w_CN");
  
  double w_l2error = 0.0, 
         w_h1error = 0.0;

  if( (es->get_mesh()).mesh_dimension() == 3 )
    {
      w_l2error = exact_sol.l2_error(system_name, "w");
      w_h1error = exact_sol.h1_error(system_name, "w");
    }

  int return_flag = 0;

  // This is the tolerance of the iterative linear solver so
  // it's unreasonable to expect anything better than this.
  double tol = 5.0e-10;
  
  if( u_l2error > tol   || u_h1error > tol   ||
      v_l2error > tol   || v_h1error > tol   ||
      w_l2error > tol   || w_h1error > tol   ||
      p_l2error > tol   || p_h1error > tol   ||
      T_l2error > tol   || T_h1error > tol   ||
      wN_l2error > tol  || wN_h1error > tol  ||
      wN2_l2error > tol || wN2_h1error > tol ||
      wCN_l2error > tol || wCN_h1error > tol )
    {
      return_flag = 1;

      std::cout << "Tolerance exceeded for solution fields." << std::endl
		<< "tolerance     = " << tol << std::endl
		<< "u l2 error    = " << u_l2error << std::endl
		<< "u h1 error    = " << u_h1error << std::endl
		<< "v l2 error    = " << v_l2error << std::endl
		<< "v h1 error    = " << v_h1error << std::endl
		<< "w l2 error    = " << w_l2error << std::endl
		<< "w h1 error    = " << w_h1error << std::endl
		<< "p l2 error    = " << p_l2error << std::endl
		<< "p h1 error    = " << p_h1error << std::endl
		<< "T l2 error    = " << T_l2error << std::endl
		<< "T h1 error    = " << T_h1error << std::endl
		<< "w_N l2 error  = " << wN_l2error << std::endl
		<< "w_N h1 error  = " << wN_h1error << std::endl
		<< "w_N2 l2 error = " << wN2_l2error << std::endl
		<< "w_N2 h1 error = " << wN2_h1error << std::endl
                << "w_CN l2 error = " << wCN_l2error << std::endl
                << "w_CN h1 error = " << wCN_h1error << std::endl;
    }

  // Now test QoI Values
  const libMesh::Real mass_loss_reg = atof(argv[3]);
  const libMesh::Real avg_N_reg = atof(argv[4]);
  
  /* The value we compute is negative by convention, but the data are given
     as positive by convention, so convert to data convention. */
  const libMesh::Real mass_loss_comp = std::fabs(grins.get_qoi_value(0));
  const libMesh::Real avg_N_comp = grins.get_qoi_value(1);
  
  const double qoi_tol = 1.0e-9;

  const double mass_loss_error = std::fabs( (mass_loss_comp - mass_loss_reg)/mass_loss_reg );

  const double avg_N_error = std::fabs( (avg_N_comp - avg_N_reg)/avg_N_reg );

  if( mass_loss_error > qoi_tol ||
      avg_N_error > qoi_tol )
    {
      return_flag = 1;

       std::cout << "Tolerance exceeded for qoi values." << std::endl
                 << "tolerance       = " << qoi_tol << std::endl
                 << "mass loss       = " << mass_loss_comp << std::endl
                 << "avg N           = " << avg_N_comp << std::endl
                 << "mass loss error = " << mass_loss_error << std::endl
                 << "avg N error     = " << avg_N_error << std::endl;
    }

  return return_flag;
}
Пример #10
0
int main(int argc, char **args) 
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Load the mesh. 
  Mesh mesh;
  H3DReader mloader;
  mloader.load("lshape_hex.mesh3d", &mesh);

  // Perform initial mesh refinement.
  for (int i=0; i < INIT_REF_NUM; i++) mesh.refine_all_elements(H3D_H3D_H3D_REFT_HEX_XYZ);

  // Create an Hcurl space with default shapeset.
  HcurlSpace space(&mesh, bc_types, essential_bc_values, Ord3(P_INIT_X, P_INIT_Y, P_INIT_Z));

  // Initialize weak formulation.
  WeakForm wf;
  wf.add_matrix_form(biform<double, scalar>, biform<Ord, Ord>, HERMES_SYM);
  wf.add_matrix_form_surf(biform_surf, biform_surf_ord);
  wf.add_vector_form_surf(liform_surf, liform_surf_ord);

  // Set exact solution.
  ExactSolution exact_sol(&mesh, exact);

  // DOF and CPU convergence graphs.
  SimpleGraph graph_dof_est, graph_cpu_est, graph_dof_exact, graph_cpu_exact; 
  
  // Adaptivity loop. 
  int as = 1; 
  bool done = false;
  do 
  {
    info("---- Adaptivity step %d:", as);

    // Construct globally refined reference mesh and setup reference space.
    Space* ref_space = construct_refined_space(&space, 1);

    // Initialize discrete problem.
    bool is_linear = true;
    DiscreteProblem dp(&wf, ref_space, is_linear);

    // Set up the solver, matrix, and rhs according to the solver selection.
    SparseMatrix* matrix = create_matrix(matrix_solver);
    Vector* rhs = create_vector(matrix_solver);
    Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);

    // Initialize the preconditioner in the case of SOLVER_AZTECOO.
    if (matrix_solver == SOLVER_AZTECOO) 
    {
      ((AztecOOSolver*) solver)->set_solver(iterative_method);
      ((AztecOOSolver*) solver)->set_precond(preconditioner);
      // Using default iteration parameters (see solver/aztecoo.h).
    }

    // Assemble the reference problem.
    info("Assembling on reference mesh (ndof: %d).", Space::get_num_dofs(ref_space));
    dp.assemble(matrix, rhs);

    // Time measurement.
    cpu_time.tick();

    // Solve the linear system on reference mesh. If successful, obtain the solution.
    info("Solving on reference mesh.");
    Solution ref_sln(ref_space->get_mesh());
    if(solver->solve()) Solution::vector_to_solution(solver->get_solution(), ref_space, &ref_sln);
    else error ("Matrix solver failed.\n");

    // Time measurement.
    cpu_time.tick();

    // Project the reference solution on the coarse mesh.
    Solution sln(space.get_mesh());
    info("Projecting reference solution on coarse mesh.");
    OGProjection::project_global(&space, &ref_sln, &sln, matrix_solver, HERMES_HCURL_NORM);

    // Time measurement.
    cpu_time.tick();

    // Output solution and mesh with polynomial orders.
    if (solution_output) 
    {
        out_fn_vtk(&sln, "sln", as);
        out_orders_vtk(&space, "order", as);
    }
  
    // Skip the visualization time.
    cpu_time.tick(HERMES_SKIP);

    // Calculate element errors and total error estimate.
    info("Calculating error estimate and exact error.");
    Adapt *adaptivity = new Adapt(&space, HERMES_HCURL_NORM);
    bool solutions_for_adapt = true;
    double err_est_rel = adaptivity->calc_err_est(&sln, &ref_sln, solutions_for_adapt) * 100;

    // Calculate exact error.
    solutions_for_adapt = false;
    double err_exact_rel = adaptivity->calc_err_exact(&sln, &exact_sol, solutions_for_adapt) * 100;

    // Report results.
    info("ndof_coarse: %d, ndof_fine: %d.", Space::get_num_dofs(&space), Space::get_num_dofs(ref_space));
    info("err_est_rel: %g%%, err_exact_rel: %g%%.", err_est_rel, err_exact_rel);

    // Add entry to DOF and CPU convergence graphs.
    graph_dof_est.add_values(Space::get_num_dofs(&space), err_est_rel);
    graph_dof_est.save("conv_dof_est.dat");
    graph_cpu_est.add_values(cpu_time.accumulated(), err_est_rel);
    graph_cpu_est.save("conv_cpu_est.dat");
    graph_dof_exact.add_values(Space::get_num_dofs(&space), err_exact_rel);
    graph_dof_exact.save("conv_dof_exact.dat");
    graph_cpu_exact.add_values(cpu_time.accumulated(), err_exact_rel);
    graph_cpu_exact.save("conv_cpu_exact.dat");

    // If err_est_rel is too large, adapt the mesh. 
    if (err_est_rel < ERR_STOP) done = true;
    else 
    {
      info("Adapting coarse mesh.");
      adaptivity->adapt(THRESHOLD);
    }
    if (Space::get_num_dofs(&space) >= NDOF_STOP) done = true;

    // Clean up.
    delete ref_space->get_mesh();
    delete ref_space;
    delete matrix;
    delete rhs;
    delete solver;
    delete adaptivity;

    // Increase the counter of performed adaptivity steps.
    as++;
  } while (!done);

  return 0;
}
int run( int argc, char* argv[], const GetPot& input, GetPot& command_line )
{
  // Initialize libMesh library.
  libMesh::LibMeshInit libmesh_init(argc, argv);

  GRINS::SimulationBuilder sim_builder;

  GRINS::Simulation grins( input,
			   sim_builder,
                           libmesh_init.comm() );

  //FIXME: We need to move this to within the Simulation object somehow...
  std::string restart_file = input( "restart-options/restart_file", "none" );

  if( restart_file == "none" )
    {
      // Asssign initial temperature value
      std::string system_name = input( "screen-options/system_name", "GRINS" );
      std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();
      const libMesh::System& system = es->get_system(system_name);

      libMesh::Parameters &params = es->parameters;

      libMesh::Real& w_N2 = params.set<libMesh::Real>( "w_N2" );
      w_N2 = input( "Physics/ReactingLowMachNavierStokes/bound_species_0", 0.0, 0.0 );

      libMesh::Real& w_N = params.set<libMesh::Real>( "w_N" );
      w_N = input( "Physics/ReactingLowMachNavierStokes/bound_species_0", 0.0, 1.0 );

      system.project_solution( initial_values, NULL, params );
    }

  grins.run();

  // Get equation systems to create ExactSolution object
  std::tr1::shared_ptr<libMesh::EquationSystems> es = grins.get_equation_system();

   // Create Exact solution object and attach exact solution quantities
  libMesh::ExactSolution exact_sol(*es);

  libMesh::EquationSystems es_ref( es->get_mesh() );

  // Filename of file where comparison solution is stashed
  std::string solution_file = command_line("soln-data", "DIE!");
  es_ref.read( solution_file );

  exact_sol.attach_reference_solution( &es_ref );

  // Now grab the variables for which we want to compare
  unsigned int n_vars = command_line.vector_variable_size("vars");
  std::vector<std::string> vars(n_vars);
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      vars[v] = command_line("vars", "DIE!", v);
    }

  // Now grab the norms to compute for each variable error
  unsigned int n_norms = command_line.vector_variable_size("norms");
  std::vector<std::string> norms(n_norms);
  for( unsigned int n = 0; n < n_norms; n++ )
    {
      norms[n] = command_line("norms", "DIE!", n);
      if( norms[n] != std::string("L2") &&
          norms[n] != std::string("H1") )
        {
          std::cerr << "ERROR: Invalid norm input " << norms[n] << std::endl
                    << "       Valid values are: L2" << std::endl
                    << "                         H1" << std::endl;
        }
    }

  const std::string& system_name = grins.get_multiphysics_system_name();

  // Now compute error for each variable
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      exact_sol.compute_error(system_name, vars[v]);
    }

  int return_flag = 0;

  double tol = command_line("tol", 1.0e-10);

  // Now test error for each variable, for each norm
  for( unsigned int v = 0; v < n_vars; v++ )
    {
      for( unsigned int n = 0; n < n_norms; n++ )
        {
          test_error_norm( exact_sol, system_name, vars[v], norms[n], tol, return_flag );
        }
    }

  return return_flag;
}
Пример #12
0
int main(int argc, char* argv[])
{
  // Check command line count.
  if( argc < 4 )
    {
      // TODO: Need more consistent error handling.
      std::cerr << "Error: Must specify libMesh input file, regression file, and regression tolerance." << std::endl;
      exit(1); // TODO: something more sophisticated for parallel runs?
    }

  // libMesh input file should be first argument
  std::string libMesh_input_filename = argv[1];
  
  // Create our GetPot object.
  GetPot libMesh_inputfile( libMesh_input_filename );

  // Initialize libMesh library.
  LibMeshInit libmesh_init(argc, argv);
 
  GRINS::SimulationBuilder sim_builder;

  GRINS::Simulation grins( libMesh_inputfile,
			   sim_builder,
                           libmesh_init.comm() );

  grins.run();

  // Get equation systems to create ExactSolution object
  std::tr1::shared_ptr<EquationSystems> es = grins.get_equation_system();

  //es->write("foobar.xdr");

  // Create Exact solution object and attach exact solution quantities
  ExactSolution exact_sol(*es);
  
  EquationSystems es_ref( es->get_mesh() );

  // Filename of file where comparison solution is stashed
  std::string solution_file = std::string(argv[2]);
  es_ref.read( solution_file );

  exact_sol.attach_reference_solution( &es_ref );
  
  std::string system_name = libMesh_inputfile( "screen-options/system_name", "GRINS" );

  // Compute error and get it in various norms
  exact_sol.compute_error(system_name, "u");
  exact_sol.compute_error(system_name, "v");

  exact_sol.compute_error(system_name, "p");

  double u_l2error = exact_sol.l2_error(system_name, "u");
  double u_h1error = exact_sol.h1_error(system_name, "u");

  double v_l2error = exact_sol.l2_error(system_name, "v");
  double v_h1error = exact_sol.h1_error(system_name, "v");

  double p_l2error = exact_sol.l2_error(system_name, "p");
  double p_h1error = exact_sol.h1_error(system_name, "p");

  int return_flag = 0;

  // This is the tolerance of the iterative linear solver so
  // it's unreasonable to expect anything better than this.
  double tol = atof(argv[3]);
  
  if( u_l2error > tol || u_h1error > tol ||
      v_l2error > tol || v_h1error > tol ||
      p_l2error > tol || p_h1error > tol  )
    {
      return_flag = 1;

      std::cout << "Tolerance exceeded for thermally driven flow test." << std::endl
		<< "tolerance = " << tol << std::endl
		<< "u l2 error = " << u_l2error << std::endl
		<< "u h1 error = " << u_h1error << std::endl
		<< "v l2 error = " << v_l2error << std::endl
		<< "v h1 error = " << v_h1error << std::endl
		<< "p l2 error = " << p_l2error << std::endl
		<< "p h1 error = " << p_h1error << std::endl;
    }

 return return_flag;
}
Пример #13
0
// exact solution
scalar2& exact(double x, double y, scalar2& dx, scalar2& dy)
{
  static scalar2 ex;
  exact_sol(x,y, ex[0], ex[1], dx[1], dy[0]);
  return ex;
}
Пример #14
0
int main() 
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Create coarse mesh, set Dirichlet BC, enumerate basis functions.
  Space* space = new Space(A, B, NELEM, DIR_BC_LEFT, DIR_BC_RIGHT, P_INIT, NEQ);

  // Enumerate basis functions, info for user.
  int ndof = Space::get_num_dofs(space);
  info("ndof: %d", ndof);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(jacobian);
  wf.add_vector_form(residual);

  // Initialize the FE problem.
  bool is_linear = false;
  DiscreteProblem *dp_coarse = new DiscreteProblem(&wf, space, is_linear);
  if(JFNK == 0)
  {
    // Newton's loop on coarse mesh.
    // Fill vector coeff_vec using dof and coeffs arrays in elements.
    double *coeff_vec_coarse = new double[Space::get_num_dofs(space)];
    get_coeff_vector(space, coeff_vec_coarse);

    // Set up the solver, matrix, and rhs according to the solver selection.
    SparseMatrix* matrix_coarse = create_matrix(matrix_solver);
    Vector* rhs_coarse = create_vector(matrix_solver);
    Solver* solver_coarse = create_linear_solver(matrix_solver, matrix_coarse, rhs_coarse);

    int it = 1;
    while (1) 
    {
      // Obtain the number of degrees of freedom.
      int ndof_coarse = Space::get_num_dofs(space);

      // Assemble the Jacobian matrix and residual vector.
      dp_coarse->assemble(coeff_vec_coarse, matrix_coarse, rhs_coarse);

      // Calculate the l2-norm of residual vector.
      double res_l2_norm = get_l2_norm(rhs_coarse);

      // Info for user.
      info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(space), res_l2_norm);

      // If l2 norm of the residual vector is within tolerance, then quit.
      // NOTE: at least one full iteration forced
      //       here because sometimes the initial
      //       residual on fine mesh is too small.
      if(res_l2_norm < NEWTON_TOL_COARSE && it > 1) break;

      // Multiply the residual vector with -1 since the matrix 
      // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n).
      for(int i = 0; i < ndof_coarse; i++) rhs_coarse->set(i, -rhs_coarse->get(i));

      // Solve the linear system.
      if(!solver_coarse->solve())
        error ("Matrix solver failed.\n");

      // Add \deltaY^{n+1} to Y^n.
      for (int i = 0; i < ndof_coarse; i++) coeff_vec_coarse[i] += solver_coarse->get_solution()[i];

      // If the maximum number of iteration has been reached, then quit.
      if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");
      
      // Copy coefficients from vector y to elements.
      set_coeff_vector(coeff_vec_coarse, space);
      
      it++;
    }
    
    // Cleanup.
    delete matrix_coarse;
    delete rhs_coarse;
    delete solver_coarse;
    delete [] coeff_vec_coarse;
  }
  else
    jfnk_cg(dp_coarse, space, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER,
            JFNK_EPSILON, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, matrix_solver);

  // Cleanup.
  delete dp_coarse;

  // DOF and CPU convergence graphs.
  SimpleGraph graph_dof_est, graph_cpu_est;
  SimpleGraph graph_dof_exact, graph_cpu_exact;

  // Adaptivity loop:
  int as = 1;
  double ftr_errors[MAX_ELEM_NUM];        // This array decides what 
                                          // elements will be refined.

  bool done = false;
  do
  {
    info("---- Adaptivity step %d:", as); 

    // Construct globally refined reference mesh and setup reference space.
    Space* ref_space = construct_refined_space(space);
 
    // Initialize the FE problem. 
    bool is_linear = false;
    DiscreteProblem* dp = new DiscreteProblem(&wf, ref_space, is_linear);
      
    if(JFNK == 0)
    {
      // Set up the solver, matrix, and rhs according to the solver selection.
      SparseMatrix* matrix = create_matrix(matrix_solver);
      Vector* rhs = create_vector(matrix_solver);
      Solver* solver = create_linear_solver(matrix_solver, matrix, rhs);
      
      // Newton's loop on the fine mesh.
      info("Solving on fine mesh:");
      // Fill vector coeff_vec using dof and coeffs arrays in elements.
      double *coeff_vec = new double[Space::get_num_dofs(ref_space)];
      get_coeff_vector(ref_space, coeff_vec);

        int it = 1;
        while (1) 
        {
          // Obtain the number of degrees of freedom.
          int ndof = Space::get_num_dofs(ref_space);

          // Assemble the Jacobian matrix and residual vector.
          dp->assemble(coeff_vec, matrix, rhs);

          // Calculate the l2-norm of residual vector.
          double res_l2_norm = get_l2_norm(rhs);

          // Info for user.
          info("---- Newton iter %d, ndof %d, res. l2 norm %g", it, Space::get_num_dofs(ref_space), res_l2_norm);

          // If l2 norm of the residual vector is within tolerance, then quit.
          // NOTE: at least one full iteration forced
          //       here because sometimes the initial
          //       residual on fine mesh is too small.
          if(res_l2_norm < NEWTON_TOL_REF && it > 1) break;

          // Multiply the residual vector with -1 since the matrix 
          // equation reads J(Y^n) \deltaY^{n+1} = -F(Y^n). 
          for(int i = 0; i < ndof; i++) rhs->set(i, -rhs->get(i));

          // Solve the linear system.
          if(!solver->solve())
            error ("Matrix solver failed.\n");

          // Add \deltaY^{n+1} to Y^n.
          for (int i = 0; i < ndof; i++) coeff_vec[i] += solver->get_solution()[i];

          // If the maximum number of iteration has been reached, then quit.
          if (it >= NEWTON_MAX_ITER) error ("Newton method did not converge.");
        
          // Copy coefficients from vector y to elements.
          set_coeff_vector(coeff_vec, ref_space);

          it++;
      }
      // Cleanup.
      delete matrix;
      delete rhs;
      delete solver;
      delete [] coeff_vec;
    }
    else
      jfnk_cg(dp, ref_space, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER,
              JFNK_EPSILON, NEWTON_TOL_COARSE, NEWTON_MAX_ITER, matrix_solver);
 
    // Cleanup.
    delete dp;
    
    // Starting with second adaptivity step, obtain new coarse 
    // mesh solution via projecting the fine mesh solution.
    if(as > 1)
    {
      info("Projecting the fine mesh solution onto the coarse mesh.");
      // Project the fine mesh solution (defined on space_ref) onto the coarse mesh (defined on space).
      OGProjection::project_global(space, ref_space, matrix_solver);
    }

    double max_qoi_err_est = 0;
    for (int i=0; i < space->get_n_active_elem(); i++)
    {
      if (GOAL_ORIENTED == 1) 
      {
        // Use quantity of interest.
        double qoi_est = quantity_of_interest(space, X_QOI);
        double qoi_ref_est = quantity_of_interest(ref_space, X_QOI);
        ftr_errors[i] = fabs(qoi_ref_est - qoi_est);
      }
      else 
      {
        // Use global norm
        double err_est_array[MAX_ELEM_NUM];
        ftr_errors[i] = calc_err_est(NORM, space, ref_space, err_est_array);
      }
      // Info for user.
      info("Elem [%d]: absolute error (est) = %g%%", i, ftr_errors[i]);

      // Time measurement.
      cpu_time.tick();

      // Calculating maximum of QOI FTR error for plotting purposes
      if (GOAL_ORIENTED == 1) 
      {
        if (ftr_errors[i] > max_qoi_err_est)
          max_qoi_err_est = ftr_errors[i];
      }
      else 
      {
        double qoi_est = quantity_of_interest(space, X_QOI);
        double qoi_ref_est = quantity_of_interest(ref_space, X_QOI);
        double err_est = fabs(qoi_ref_est - qoi_est);
        if (err_est > max_qoi_err_est)
          max_qoi_err_est = err_est;
      }
    }

    // Add entries to convergence graphs.
    if (EXACT_SOL_PROVIDED) 
    {
      double qoi_est = quantity_of_interest(space, X_QOI);
      double u[MAX_EQN_NUM], dudx[MAX_EQN_NUM];
      exact_sol(X_QOI, u, dudx);
      double err_qoi_exact = fabs(u[0] - qoi_est);
      // Info for user.
      info("Relative error (exact) = %g %%", err_qoi_exact);
      // Add entry to DOF and CPU convergence graphs.
      graph_dof_exact.add_values(Space::get_num_dofs(space), err_qoi_exact);
      graph_cpu_exact.add_values(cpu_time.accumulated(), err_qoi_exact);
    }
    
    // Add entry to DOF and CPU convergence graphs.
    graph_dof_est.add_values(Space::get_num_dofs(space), max_qoi_err_est);
    graph_cpu_est.add_values(cpu_time.accumulated(), max_qoi_err_est);

    // Decide whether the max. FTR error in the quantity of interest 
    // is sufficiently small.
    if(max_qoi_err_est < TOL_ERR_QOI) break;

    // Returns updated coarse and fine meshes, with the last 
    // coarse and fine mesh solutions on them, respectively. 
    // The coefficient vectors and numbers of degrees of freedom 
    // on both meshes are also updated. 
    adapt(NORM, ADAPT_TYPE, THRESHOLD, ftr_errors, space, ref_space);

    as++;

    // Plot meshes, results, and errors.
    adapt_plotting(space, ref_space, NORM, EXACT_SOL_PROVIDED, exact_sol);

    // Cleanup.
    delete ref_space;
  }
  while (done == false);

  info("Total running time: %g s", cpu_time.accumulated());

  // Save convergence graphs.
  graph_dof_est.save("conv_dof_est.dat");
  graph_cpu_est.save("conv_cpu_est.dat");
  graph_dof_exact.save("conv_dof_exact.dat");
  graph_cpu_exact.save("conv_cpu_exact.dat");

  // Test variable.
  bool success = true;
  info("ndof = %d.", Space::get_num_dofs(space));
  if (Space::get_num_dofs(space) > 150) success = false;

  if (success)
  {
    info("Success!");
    return ERROR_SUCCESS;
  }
  else
  {
    info("Failure!");
    return ERROR_FAILURE;
  }
}
Пример #15
0
int main() {
  // Create coarse mesh, set Dirichlet BC, enumerate 
  // basis functions
  Mesh *mesh = new Mesh(A, B, N_elem, P_init, N_eq);
  mesh->set_bc_left_dirichlet(0, Val_dir_left);
  mesh->set_bc_right_dirichlet(0, Val_dir_right);
  mesh->assign_dofs();

  // Create discrete problem on coarse mesh
  DiscreteProblem *dp = new DiscreteProblem();
  dp->add_matrix_form(0, 0, jacobian);
  dp->add_vector_form(0, residual);

  // Convergence graph wrt. the number of degrees of freedom
  // (goal-oriented adaptivity)
  GnuplotGraph graph_ftr;
  graph_ftr.set_log_y();
  graph_ftr.set_captions("Convergence History", "Degrees of Freedom", "QOI error");
  graph_ftr.add_row("QOI error - FTR (exact)", "k", "-", "o");
  graph_ftr.add_row("QOI error - FTR (est)", "k", "--");

  // Main adaptivity loop
  int adapt_iterations = 1;
  double ftr_errors[MAX_ELEM_NUM];      // This array decides what 
                                         // elements will be refined.
  ElemPtr2 ref_ftr_pairs[MAX_ELEM_NUM]; // To store element pairs from the 
                                         // FTR solution. Decides how 
                                         // elements will be hp-refined. 
  for (int i=0; i < MAX_ELEM_NUM; i++) {
    ref_ftr_pairs[i][0] = new Element();
    ref_ftr_pairs[i][1] = new Element();
  }
  while(1) {
    printf("============ Adaptivity step %d ============\n", adapt_iterations); 

    printf("N_dof = %d\n", mesh->get_n_dof());
 
    // Newton's loop on coarse mesh
    int success;
    if(JFNK == 0) {
      newton(dp, mesh, NULL, NEWTON_TOL_COARSE, NEWTON_MAXITER);
    }
    else {
      jfnk_cg(dp, mesh, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER,
              JFNK_EPSILON, NEWTON_TOL_COARSE, NEWTON_MAXITER);
    }
    // For every element perform its fast trial refinement (FTR),
    // calculate the norm of the difference between the FTR
    // solution and the coarse mesh solution, and store the
    // error in the ftr_errors[] array.
    int n_elem = mesh->get_n_active_elem();
    double max_qoi_err_est = 0;
    for (int i=0; i < n_elem; i++) {

      printf("=== Starting FTR of Elem [%d]\n", i);

      // Replicate coarse mesh including solution.
      Mesh *mesh_ref_local = mesh->replicate();

      // Perform FTR of element 'i'
      mesh_ref_local->reference_refinement(i, 1);
      printf("Elem [%d]: fine mesh created (%d DOF).\n", 
             i, mesh_ref_local->assign_dofs());

      // Newton's loop on the FTR mesh
      if(JFNK == 0) {
        newton(dp, mesh_ref_local, NULL, NEWTON_TOL_COARSE, NEWTON_MAXITER);
      }
      else {
        jfnk_cg(dp, mesh_ref_local, MATRIX_SOLVER_TOL, MATRIX_SOLVER_MAXITER, 
                JFNK_EPSILON, NEWTON_TOL_REF, NEWTON_MAXITER);
      }

      // Print FTR solution (enumerated) 
      Linearizer *lxx = new Linearizer(mesh_ref_local);
      char out_filename[255];
      sprintf(out_filename, "solution_ref_%d.gp", i);
      lxx->plot_solution(out_filename);
      delete lxx;

      // Calculate FTR errors for refinement purposes
      if (GOAL_ORIENTED == 1) {
        // Use quantity of interest.
        double qoi_est = quantity_of_interest(mesh, X_QOI);
        double qoi_ref_est = quantity_of_interest(mesh_ref_local, X_QOI);
        ftr_errors[i] = fabs(qoi_ref_est - qoi_est);
      }
      else {
        // Use global norm
        double err_est_array[MAX_ELEM_NUM];
        ftr_errors[i] = calc_error_estimate(NORM, mesh, mesh_ref_local, 
                                            err_est_array);
      }

      // Calculating maximum of QOI FTR error for plotting purposes
      if (GOAL_ORIENTED == 1) {
        if (ftr_errors[i] > max_qoi_err_est) 
	  max_qoi_err_est = ftr_errors[i];
      }
      else {
        double qoi_est = quantity_of_interest(mesh, X_QOI);
        double qoi_ref_est = quantity_of_interest(mesh_ref_local, X_QOI);
        double err_est = fabs(qoi_ref_est - qoi_est);
        if (err_est > max_qoi_err_est) 
	  max_qoi_err_est = err_est;
      }

      // Copy the reference element pair for element 'i'
      // into the ref_ftr_pairs[i][] array
      Iterator *I = new Iterator(mesh);
      Iterator *I_ref = new Iterator(mesh_ref_local);
      Element *e, *e_ref;
      while (1) {
        e = I->next_active_element();
        e_ref = I_ref->next_active_element();
        if (e->id == i) {
  	  e_ref->copy_into(ref_ftr_pairs[e->id][0]);
          // coarse element 'e' was split in space
          if (e->level != e_ref->level) {
            e_ref = I_ref->next_active_element();
            e_ref->copy_into(ref_ftr_pairs[e->id][1]);
          }
          break;
        }
      }

      delete I;
      delete I_ref;
      delete mesh_ref_local;
    }  

    // Add entries to convergence graphs
    if (EXACT_SOL_PROVIDED) {
      double qoi_est = quantity_of_interest(mesh, X_QOI);
      double u[MAX_EQN_NUM], dudx[MAX_EQN_NUM];
      exact_sol(X_QOI, u, dudx);
      double err_qoi_exact = fabs(u[0] - qoi_est);
      // plotting error in quantity of interest wrt. exact value
      graph_ftr.add_values(0, mesh->get_n_dof(), err_qoi_exact);
    }
    graph_ftr.add_values(1, mesh->get_n_dof(), max_qoi_err_est);

    // Decide whether the max. FTR error in the quantity of interest 
    // is sufficiently small
    if(max_qoi_err_est < TOL_ERR_QOI) break;

    // debug
    if (adapt_iterations == 3) break;

    // Returns updated coarse mesh with the last solution on it. 
    adapt(NORM, ADAPT_TYPE, THRESHOLD, ftr_errors,
          mesh, ref_ftr_pairs);

    adapt_iterations++;
  }

  // Plot meshes, results, and errors
  adapt_plotting(mesh, ref_ftr_pairs,
                 NORM, EXACT_SOL_PROVIDED, exact_sol);

  // Save convergence graph
  graph_ftr.save("conv_dof.gp");

  printf("Done.\n");
  return 1;
}
Пример #16
0
int main(int argc, char* argv[])
{
#ifdef GRINS_USE_GRVY_TIMERS
  GRVY::GRVY_Timer_Class grvy_timer;
  grvy_timer.Init("GRINS Timer");
#endif
	// Check command line count.
	if( argc < 3 )
	{
		// TODO: Need more consistent error handling.
		std::cerr << "Error: Must specify libMesh input file." << std::endl;
		exit(1); // TODO: something more sophisticated for parallel runs?
	}

	// libMesh input file should be first argument
	std::string libMesh_input_filename = argv[1];

	// Create our GetPot object.
	GetPot libMesh_inputfile( libMesh_input_filename );

	// GetPot doesn't throw an error for a nonexistent file?
	{
		std::ifstream i(libMesh_input_filename.c_str());
		if (!i)
		{
			std::cerr << "Error: Could not read from libMesh input file "
					<< libMesh_input_filename << std::endl;
			exit(1);
		}
	}

	// Initialize libMesh library.
	libMesh::LibMeshInit libmesh_init(argc, argv);

	libMesh::out << "Starting GRINS with command:\n";
	for (int i=0; i != argc; ++i)
		libMesh::out << argv[i] << ' ';
	libMesh::out << std::endl;

	GRINS::SimulationBuilder sim_builder;

	GRINS::Simulation grins( libMesh_inputfile,
						     sim_builder,
						     libmesh_init.comm() );

	std::string system_name = libMesh_inputfile( "screen-options/system_name", "GRINS" );

	// Get equation systems
	GRINS::SharedPtr<libMesh::EquationSystems> es = grins.get_equation_system();
	const libMesh::System& system = es->get_system(system_name);

	libMesh::Parameters &params = es->parameters;

	system.project_solution( initial_values, NULL, params );

	grins.run();

	//es->write("suspended_cable_test.xdr");

	// Create Exact solution object and attach exact solution quantities
	libMesh::ExactSolution exact_sol(*es);

	libMesh::EquationSystems es_ref( es->get_mesh() );

	// Filename of file where comparison solution is stashed
	std::string solution_file = std::string(argv[2]);
	es_ref.read( solution_file );

	exact_sol.attach_reference_solution( &es_ref );

	// Compute error and get it in various norms
	exact_sol.compute_error(system_name, "u");
	exact_sol.compute_error(system_name, "v");
	exact_sol.compute_error(system_name, "w");

	double u_l2error = exact_sol.l2_error(system_name, "u");
	double u_h1error = exact_sol.h1_error(system_name, "u");

	double v_l2error = exact_sol.l2_error(system_name, "v");
	double v_h1error = exact_sol.h1_error(system_name, "v");

	double w_l2error = exact_sol.l2_error(system_name, "w");
	double w_h1error = exact_sol.h1_error(system_name, "w");

	int return_flag = 0;

	double tol = 5.0e-8;

	if( u_l2error > tol   || u_h1error > tol   ||
	    v_l2error > tol   || v_h1error > tol   ||
	    w_l2error > tol   || w_h1error > tol     )
	{
	  return_flag = 1;

	  std::cout << "Tolerance exceeded for suspended cable test." << std::endl
		<< "tolerance     = " << tol << std::endl
		<< "u l2 error    = " << u_l2error << std::endl
		<< "u h1 error    = " << u_h1error << std::endl
		<< "v l2 error    = " << v_l2error << std::endl
		<< "v h1 error    = " << v_h1error << std::endl
		<< "w l2 error    = " << w_l2error << std::endl
		<< "w h1 error    = " << w_h1error << std::endl;
	}

	return return_flag;
}