Пример #1
0
L2Space::L2Space(Mesh* mesh, int p_init, Shapeset* shapeset)
  : Space(mesh, shapeset, NULL, NULL, Ord2(p_init, p_init))
{
  if (shapeset == NULL) this->shapeset = new L2Shapeset;
  ldata = NULL;
  lsize = 0;

  // set uniform poly order in elements
  if (p_init < 0) error("P_INIT must be >= 0 in an L2 space.");
  else this->set_uniform_order_internal(Ord2(p_init, p_init));

  // enumerate basis functions
  this->assign_dofs();
}
Пример #2
0
// the following constructors are DEPRECATED.
HdivSpace::HdivSpace(Mesh* mesh, BCTypes* bc_types,
                 scalar (*bc_value_callback_by_coord)(int, double, double), int p_init, 
                 Shapeset* shapeset) : Space(mesh, shapeset, bc_types, bc_value_callback_by_coord, Ord2(p_init, p_init))
{
  if (shapeset == NULL)
  {
    this->shapeset = new HdivShapeset;
    own_shapeset = true;
  }
  if (this->shapeset->get_num_components() < 2) error("HdivSpace requires a vector shapeset.");

  if (!hdiv_proj_ref++)
  {
    precalculate_projection_matrix(0, hdiv_proj_mat, hdiv_chol_p);
  }

  proj_mat = hdiv_proj_mat;
  chol_p   = hdiv_chol_p;

  // set uniform poly order in elements
  if (p_init < 0) error("P_INIT must be >= 0 in an Hdiv space.");
  else this->set_uniform_order_internal(Ord2(p_init, p_init));

  // enumerate basis functions
  this->assign_dofs();
}
Пример #3
0
// DEPRECATED
H1Space::H1Space(Mesh* mesh, BCType (*bc_type_callback)(int), 
	  scalar (*bc_value_callback_by_coord)(int, double, double), int p_init,
    Shapeset* shapeset) : Space(mesh, shapeset, bc_type_callback, bc_value_callback_by_coord, Ord2(p_init, p_init))
{
  _F_
  if (shapeset == NULL) 
  {
    this->shapeset = new H1Shapeset;
    own_shapeset = true;
  }

  if (!h1_proj_ref++)
  {
    // FIXME: separate projection matrices for different shapesets
    precalculate_projection_matrix(2, h1_proj_mat, h1_chol_p);
  }
  proj_mat = h1_proj_mat;
  chol_p   = h1_chol_p;

  // set uniform poly order in elements
  if (p_init < 1) error("P_INIT must be >=  1 in an H1 space.");
  else this->set_uniform_order_internal(Ord2(p_init, p_init));

  // enumerate basis functions
  this->assign_dofs();
}
Пример #4
0
Space* HdivSpace::dup(Mesh* mesh) const
{
  HdivSpace* space = new HdivSpace(mesh, this->bc_types,
          this->bc_value_callback_by_coord, Ord2(0,0), this->shapeset);
  space->copy_callbacks(this);
  return space;
}
Пример #5
0
int test_order_hex() {
	info("test_order_hex.");

	Ord3 a(1, 2, 3), b(3, 4, 2);
	Ord3 x;

	Ord3 c = a + b;
	if (c.x != 4 || c.y != 6 || c.z != 5) return ERR_FAILURE;

	Ord3 d = a;
	d += b;
	if (d.x != 4 || d.y != 6 || c.z != 5) return ERR_FAILURE;

	Ord3 e = b * 6;
	if (e.x != 18 || e.y != 24 || e.z != 12) return ERR_FAILURE;

	Ord3 f = b * Ord3(2, 3, 4);
	if (f.x != 6 || f.y != 12 || f.z != 8) return ERR_FAILURE;

	Ord3 m = max(b, e);
	if (m.x != e.x || m.y != e.y || m.z != e.z) return ERR_FAILURE;

	Ord3 z(2, 1, 4);
	x = a + b + z;
	if (x.x != 6 || x.y != 7 || x.z != 9) return ERR_FAILURE;

	if (c == Ord3(4, 6, 5)) ;
	else return ERR_FAILURE;

	if (c != Ord3(4, 6, 5)) return ERR_FAILURE;

	Ord1 edge_ref_order[] = { 3, 4, 3, 4, 2, 2, 2, 2, 3, 4, 3, 4 };
	for (int iedge = 0; iedge < Hex::NUM_EDGES; iedge++) {
		if (b.get_edge_order(iedge) != edge_ref_order[iedge]) return ERR_FAILURE;
	}

	Ord2 face_ref_order[] = {
		Ord2(4, 2), Ord2(4, 2), Ord2(3, 2), Ord2(3, 2), Ord2(3, 4), Ord2(3, 4)
	};
	for (int iface = 0; iface < Hex::NUM_FACES; iface++) {
		if (b.get_face_order(iface) != face_ref_order[iface]) return ERR_FAILURE;
	}

	return ERR_SUCCESS;
}
Пример #6
0
int test_order_quad() {
	info("test_order_quad.");

	Ord2 a(1, 2), b(3, 4);

	Ord2 c = a + b;
	if (c.x != 4 || c.y != 6) return ERR_FAILURE;

	Ord2 d = a;
	d += b;
	if (d.x != 4 || d.y != 6) return ERR_FAILURE;

	Ord2 e = b * 6;
	if (e.x != 18 || e.y != 24) return ERR_FAILURE;

	Ord2 f = b * Ord2(2, 3);
	if (f.x != 6 || f.y != 12) return ERR_FAILURE;

	Ord2 m = max(b, e);
	if (m.x != e.x || m.y != e.y) return ERR_FAILURE;

	return ERR_SUCCESS;
}
Пример #7
0
int test_quadrature_3d_hex_surf(fn3d_t fn, double exact, int min_h, int min_v, int min_u, const char *fn_name) {
	info("  * f(x,y) = %s", fn_name);

	QuadStdHex quad;
	for (int horder = min_h; horder <= H3D_MAX_QUAD_ORDER; horder++) {
		for (int vorder = min_v; vorder <= H3D_MAX_QUAD_ORDER; vorder++) {
			for (int uorder = min_u; uorder <= H3D_MAX_QUAD_ORDER; uorder++) {
				Ord2 face_order[] = {
					Ord2(vorder, uorder),
					Ord2(vorder, uorder),
					Ord2(horder, uorder),
					Ord2(horder, uorder),
					Ord2(horder, vorder),
					Ord2(horder, vorder)
				};

				double integral = 0;
				for (int face = 0; face < Hex::NUM_FACES; face++) {
					Ord2 order = face_order[face];
					int np = quad.get_face_num_points(face, order);
					QuadPt3D *pt = quad.get_face_points(face, order);

					for (int i = 0; i < np; i++)
						integral += fn(pt[i].x, pt[i].y, pt[i].z) * pt[i].w;
				}

				double err = fabs(exact - integral);
				if (err >= EPS) {
					info(" ... failed for order (h = %d, v = %d, u = %d), integral = %lf, expected = %lf (diff = %e).",
						horder, vorder, uorder, integral, exact, fabs(integral - exact));
					return ERR_FAILURE;
				}
			}
		}
	}

	info(" ... OK.");

	return ERR_SUCCESS;
}
Пример #8
0
//
//  BC: Normal velocity component is zero on solid walls.
//      Subsonic state prescribed on inlet and outlet.
//
//  IC: Constant subsonic state identical to inlet. 
//
//  The following parameters can be changed:

// Experimental caching of vector valued (vector) forms.
#define HERMES_USE_VECTOR_VALUED_FORMS

// Calculation of approximation of time derivative (and its output).
// Setting this option to false saves the computation time.
const bool CALC_TIME_DER = true;

const Ord2 P_INIT = Ord2(0,0);                    // Initial polynomial degree.                      
const int INIT_REF_NUM = 4;                       // Number of initial uniform mesh refinements.                       
double CFL = 0.8;                                 // CFL value.
double TAU = 1E-4;                                // Time step.
MatrixSolverType matrix_solver = SOLVER_UMFPACK;  // Possibilities: SOLVER_AMESOS, SOLVER_AZTECOO, SOLVER_MUMPS,
                                                  // SOLVER_PARDISO, SOLVER_PETSC, SOLVER_SUPERLU, SOLVER_UMFPACK.

// Equation parameters.
double P_EXT = 2.5;         // Exterior pressure (dimensionless).
double RHO_EXT = 1.0;       // Inlet density (dimensionless).   
double V1_EXT = 1.25;       // Inlet x-velocity (dimensionless).
double V2_EXT = 0.0;        // Inlet y-velocity (dimensionless).
double KAPPA = 1.4;         // Kappa.

double t = 0;
Пример #9
0
HcurlSpace::HcurlSpace(Mesh* mesh, int p_init, Shapeset* shapeset)
    : Space(mesh, shapeset, NULL, Ord2(p_init, p_init))
{
  _F_
  init(shapeset, Ord2(p_init, p_init));
}
Пример #10
0
HcurlSpace::HcurlSpace(Mesh* mesh, EssentialBCs* essential_bcs, int p_init, Shapeset* shapeset)
    : Space(mesh, shapeset, essential_bcs, Ord2(p_init, p_init))
{
  _F_
  init(shapeset, Ord2(p_init, p_init));
}
Пример #11
0
// Meaning: 0 - concentration is kept constant at the bottom of the domain.
//              at the beginning, concentration is equal throughout the whole
//              domain and is equal to the value at the bottom.
//          1 - concentration is kept constant at the bottom of the domain.
//              at the beginning, concentration is zero throughout the domain.
//          2 - concentration is kept constant at the inlet part of the domain.
//              at the beginning, concentration is zero throughout the domain.
// If not said otherwise, zero Neumann condition is imposed on all parts of the boundary.
unsigned int INITIAL_CONCENTRATION_STATE = 0;

// Visualization.
const bool HERMES_VISUALIZATION = false;           // Set to "true" to enable Hermes OpenGL visualization. 
const bool VTK_OUTPUT = true;                     // Set to "true" to enable VTK output.
const unsigned int EVERY_NTH_STEP = 50;            // Set visual output for every nth step.

const Ord2 P_INIT_FLOW = Ord2(0,0);               // Polynomial degree for the Euler equations (for the flow).
const Ord2 P_INIT_CONCENTRATION = Ord2(1,1);      // Polynomial degree for the concentration.
double CFL = 0.8;                                 // CFL value.
double TAU = 1E-4;                                // Time step.
const MatrixSolverType matrix_solver = SOLVER_UMFPACK;  // Possibilities: SOLVER_AMESOS, SOLVER_AZTECOO, SOLVER_MUMPS,
                                                  // SOLVER_PETSC, SOLVER_SUPERLU, SOLVER_UMFPACK.

unsigned int INIT_REF_NUM_FLOW = 2;         // Number of initial uniform mesh refinements of the mesh for the flow.
unsigned int INIT_REF_NUM_CONCENTRATION = 4;// Number of initial uniform mesh refinements of the mesh for the concentration.


// Equation parameters.
const double P_EXT = 2.5;         // Exterior pressure (dimensionless).
const double RHO_EXT = 1.0;       // Inlet density (dimensionless).   
const double V1_EXT = 1.25;       // Inlet x-velocity (dimensionless).
const double V2_EXT = 0.0;        // Inlet y-velocity (dimensionless).
Пример #12
0
H1Space::H1Space(Mesh* mesh, BCTypes* bc_types, BCValues* bc_values, int p_init, Shapeset* shapeset)
    : Space(mesh, shapeset, bc_types, bc_values, Ord2(p_init, p_init))
{
  _F_
  init(shapeset, Ord2(p_init, p_init));
}
Пример #13
0
HdivSpace::HdivSpace(Mesh* mesh, BCTypes* bc_types, int p_init, Shapeset* shapeset)
  : Space(mesh, shapeset, bc_types, (BCValues*) NULL, Ord2(p_init, p_init))
{
  init(shapeset, Ord2(p_init, p_init));
}
Пример #14
0
int main(int argc, char* argv[])
{
    // Time measurement.
    TimePeriod cpu_time;
    cpu_time.tick();

    // Load the mesh.
    Mesh mesh;
    H2DReader mloader;
    mloader.load("square.mesh", &mesh);
    //mloader.load("square-tri.mesh", &mesh);

    // Perform initial mesh refinements.
    for (int i=0; i<INIT_REF; i++) mesh.refine_all_elements();

    // Create an L2 space with default shapeset.
    L2Space space(&mesh, bc_types, NULL, Ord2(P_H, P_V));
    int ndof = Space::get_num_dofs(&space);
    info("ndof = %d", ndof);

    // Initialize the weak formulation.
    WeakForm wf;
    wf.add_matrix_form(callback(bilinear_form));
    wf.add_vector_form(callback(linear_form));
    wf.add_matrix_form_surf(callback(bilinear_form_boundary), H2D_DG_BOUNDARY_EDGE);
    wf.add_vector_form_surf(callback(linear_form_boundary), H2D_DG_BOUNDARY_EDGE);
    wf.add_matrix_form_surf(callback(bilinear_form_interface), H2D_DG_INNER_EDGE);

    // Initialize the FE problem.
    bool is_linear = true;
    DiscreteProblem dp(&wf, &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).
    }

    // Initialize the solution.
    Solution sln;

    // Assemble the stiffness matrix and right-hand side vector.
    info("Assembling the stiffness matrix and right-hand side vector.");
    dp.assemble(matrix, rhs);

    // Solve the linear system and if successful, obtain the solution.
    info("Solving the matrix problem.");
    if(solver->solve())
        Solution::vector_to_solution(solver->get_solution(), &space, &sln);
    else
        error ("Matrix solver failed.\n");

    // Time measurement.
    cpu_time.tick();

    // Clean up.
    delete solver;
    delete matrix;
    delete rhs;

    // Visualize the solution.
    ScalarView view1("Solution", new WinGeom(860, 0, 400, 350));
    view1.show(&sln);

    // Wait for all views to be closed.
    View::wait();

    return 0;
}
Пример #15
0
int main(int argc, char* argv[])
{
  /* So far the DG assembling is very slow for higher order polynomials,
      so only constant functions are used here.
  if(argc < 3)
    error("Too few arguments in example-euler-gamm-explicit");

  Ord2 P_INIT= Ord2(atoi(argv[1]), atoi(argv[2]));
  */

  Ord2 P_INIT= Ord2(0, 0);

  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("GAMM-channel.mesh", &mesh);

  // Perform initial mesh refinements.
  for (int i = 0; i < INIT_REF_NUM; i++) mesh.refine_all_elements();
  mesh.refine_towards_boundary(1, 1);
  mesh.refine_element_id(1053);
  mesh.refine_element_id(1054);
  mesh.refine_element_id(1087);
  mesh.refine_element_id(1088);
  mesh.refine_element_id(1117);
  mesh.refine_element_id(1118);
  mesh.refine_element_id(1151);
  mesh.refine_element_id(1152);

  // Enter boundary markers.  
  BCTypes bc_types;
  bc_types.add_bc_neumann(Hermes::vector<int>(BDY_SOLID_WALL, BDY_INLET_OUTLET));

  // Create L2 spaces with default shapesets.
  L2Space space_rho(&mesh, &bc_types, P_INIT);
  L2Space space_rho_v_x(&mesh, &bc_types, P_INIT);
  L2Space space_rho_v_y(&mesh, &bc_types, P_INIT);
  L2Space space_e(&mesh, &bc_types, P_INIT);

  // Initialize solutions, set initial conditions.
  Solution sln_rho, sln_rho_v_x, sln_rho_v_y, sln_e, prev_rho, prev_rho_v_x, prev_rho_v_y, prev_e;
  sln_rho.set_exact(&mesh, ic_density);
  sln_rho_v_x.set_exact(&mesh, ic_density_vel_x);
  sln_rho_v_y.set_exact(&mesh, ic_density_vel_y);
  sln_e.set_exact(&mesh, ic_energy);
  prev_rho.set_exact(&mesh, ic_density);
  prev_rho_v_x.set_exact(&mesh, ic_density_vel_x);
  prev_rho_v_y.set_exact(&mesh, ic_density_vel_y);
  prev_e.set_exact(&mesh, ic_energy);

  // Initialize weak formulation.
  WeakForm wf(4);

  // Bilinear forms coming from time discretization by explicit Euler's method.
  wf.add_matrix_form(0, 0, callback(bilinear_form_0_0_time));
  wf.add_matrix_form(1, 1, callback(bilinear_form_1_1_time));
  wf.add_matrix_form(2, 2, callback(bilinear_form_2_2_time));
  wf.add_matrix_form(3, 3, callback(bilinear_form_3_3_time));

  // Volumetric linear forms.
  // Linear forms coming from the linearization by taking the Eulerian fluxes' Jacobian matrices 
  // from the previous time step.
  // Unnecessary for FVM.
  if(P_INIT.order_h > 0 || P_INIT.order_v > 0) {
    // First flux.
    wf.add_vector_form(0, callback(linear_form_0_1), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_x));
    
    wf.add_vector_form(1, callback(linear_form_1_0_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_1_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_2_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_3_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(2, callback(linear_form_2_0_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_1_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_2_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_3_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_0_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_1_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_2_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_3_first_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    // Second flux.
    
    wf.add_vector_form(0, callback(linear_form_0_2), HERMES_ANY, Hermes::vector<MeshFunction*>(&prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_0_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_1_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_2_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(1, callback(linear_form_1_3_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(2, callback(linear_form_2_0_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_1_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_2_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y));
    wf.add_vector_form(2, callback(linear_form_2_3_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_0_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_1_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_2_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
    wf.add_vector_form(3, callback(linear_form_3_3_second_flux), HERMES_ANY, 
                       Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  }

  // Volumetric linear forms coming from the time discretization.
  wf.add_vector_form(0, linear_form, linear_form_order, HERMES_ANY, &prev_rho);
  wf.add_vector_form(1, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_x);
  wf.add_vector_form(2, linear_form, linear_form_order, HERMES_ANY, &prev_rho_v_y);
  wf.add_vector_form(3, linear_form, linear_form_order, HERMES_ANY, &prev_e);

  // Surface linear forms - inner edges coming from the DG formulation.
  wf.add_vector_form_surf(0, linear_form_interface_0, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(1, linear_form_interface_1, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(2, linear_form_interface_2, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(3, linear_form_interface_3, linear_form_order, H2D_DG_INNER_EDGE, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));

  // Surface linear forms - inlet / outlet edges.
  wf.add_vector_form_surf(0, bdy_flux_inlet_outlet_comp_0, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(1, bdy_flux_inlet_outlet_comp_1, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(2, bdy_flux_inlet_outlet_comp_2, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(3, bdy_flux_inlet_outlet_comp_3, linear_form_order, BDY_INLET_OUTLET, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));

  
  // Surface linear forms - Solid wall edges.
  wf.add_vector_form_surf(0, bdy_flux_solid_wall_comp_0, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(1, bdy_flux_solid_wall_comp_1, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(2, bdy_flux_solid_wall_comp_2, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));
  wf.add_vector_form_surf(3, bdy_flux_solid_wall_comp_3, linear_form_order, BDY_SOLID_WALL, 
                          Hermes::vector<MeshFunction*>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e));


  // Initialize the FE problem.
  bool is_linear = true;
  
  DiscreteProblem dp(&wf, Hermes::vector<Space*>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e), is_linear);
  
  // If the FE problem is in fact a FV problem.
  if(P_INIT.order_h == 0 && P_INIT.order_v == 0)
    dp.set_fvm();

  // Iteration number.
  int iteration = 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);

  // For testing purposes.
  double l2_norms[5][4];
  for(unsigned int i = 0; i < 5; i++)
    for(unsigned int j = 0; j < 4; j++)
      l2_norms[i][j] = 0.0;
  double point_values[5][3];
  for(unsigned int i = 0; i < 5; i++)
    for(unsigned int j = 0; j < 3; j++)
      point_values[i][j] = 0.0;
  // Calculate the special point where we will evaluate the solution.
  double x = 0.75;
  double y = sqrt((double)(1.-x*x)) + 0.001;

  for(unsigned int time_step = 0; time_step < 5; time_step++)
  {
    iteration++;

    bool rhs_only = (iteration == 1 ? false : true);
    // Assemble stiffness matrix and rhs or just rhs.
    if (rhs_only == false) info("Assembling the stiffness matrix and right-hand side vector.");
    else info("Assembling the right-hand side vector (only).");
    dp.assemble(matrix, rhs, rhs_only);

        
    // Solve the matrix problem.
    info("Solving the matrix problem.");
    if(solver->solve())
      Solution::vector_to_solutions(solver->get_solution(), Hermes::vector<Space *>(&space_rho, &space_rho_v_x, 
      &space_rho_v_y, &space_e), Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e));
    else
    error ("Matrix solver failed.\n");

    // Approximate the time derivative of the solution.
    if(CALC_TIME_DER) {
      Adapt *adapt_for_time_der_calc = new Adapt(Hermes::vector<Space *>(&space_rho, &space_rho_v_x, &space_rho_v_y, &space_e));
      bool solutions_for_adapt = false;
      double difference = iteration == 1 ? 0 : 
        adapt_for_time_der_calc->calc_err_est(Hermes::vector<Solution *>(&prev_rho, &prev_rho_v_x, &prev_rho_v_y, &prev_e), 
					      Hermes::vector<Solution *>(&sln_rho, &sln_rho_v_x, &sln_rho_v_y, &sln_e), 
                                              (Hermes::vector<double>*) NULL, solutions_for_adapt, 
                                              HERMES_TOTAL_ERROR_ABS | HERMES_ELEMENT_ERROR_ABS) / TAU;
      delete adapt_for_time_der_calc;
    }

    // Determine the time step according to the CFL condition.
    // Only mean values on an element of each solution component are taken into account.
    double *solution_vector = solver->get_solution();
    double min_condition = 0;
    Element *e;
    for (int _id = 0, _max = mesh.get_max_element_id(); _id < _max; _id++) \
          if (((e) = mesh.get_element_fast(_id))->used) \
            if ((e)->active) {
              AsmList al;
              space_rho.get_element_assembly_list(e, &al);
              double rho = solution_vector[al.dof[0]];
              space_rho_v_x.get_element_assembly_list(e, &al);
              double v1 = solution_vector[al.dof[0]] / rho;
              space_rho_v_y.get_element_assembly_list(e, &al);
              double v2 = solution_vector[al.dof[0]] / rho;
              space_e.get_element_assembly_list(e, &al);
              double energy = solution_vector[al.dof[0]];
              double condition = e->get_area() / (std::sqrt(v1*v1 + v2*v2) + calc_sound_speed(rho, rho*v1, rho*v2, energy));
              if(condition < min_condition || min_condition == 0.)
                min_condition = condition;
            }
    if(TAU > min_condition)
      TAU = min_condition;
    if(TAU < min_condition * 0.9)
      TAU = min_condition;

    // Storing the testing values.
    for(unsigned int j = 0; j < 4; j++)
      for(unsigned int k = j*space_rho.get_num_dofs(); k < (j+1)*space_rho.get_num_dofs(); k++)
        l2_norms[time_step][j] += solver->get_solution()[k];    

    point_values[time_step][0] = sln_rho_v_x.get_pt_value(0.5, 0.001);
    point_values[time_step][1] = sln_rho_v_x.get_pt_value(x, y);
    point_values[time_step][2] = sln_rho_v_x.get_pt_value(1.5, 0.001);

    // Copy the solutions into the previous time level ones.
    prev_rho.copy(&sln_rho);
    prev_rho_v_x.copy(&sln_rho_v_x);
    prev_rho_v_y.copy(&sln_rho_v_y);
    prev_e.copy(&sln_e);
  }
  bool okay = true;
  switch(P_INIT.order_h* 10 + P_INIT.order_v) {
  case 0:
    if(std::abs(l2_norms[0][0] - 888.0) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[0][1] - 1110) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[0][2]) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[0][3] - 6243.75) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][0] - 887.99997637865545) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][1] - 1109.9997956458228) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][2] - 3.1927018090871903e-008) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[1][3] - 6243.7496921971369) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][0] - 887.99993429457072) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][1] - 1109.9994322038613) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][2] + 5.3556469633245445e-008) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[2][3] - 6243.7491437826511) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][0] - 887.99987376550200) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][1] - 1109.9989102977672) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][2] + 3.6958140470412712e-007) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[3][3] - 6243.7483549661320) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][0] - 887.99979481320088) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][1] - 1109.9982305630808) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][2] + 1.0303296924184822e-006) > 1E-8)
      okay = false;
    if(std::abs(l2_norms[4][3] - 6243.7473260085462) > 1E-8)
      okay = false;

    // points
    if(std::abs(point_values[0][0] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[0][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[0][2] - 1.2459744738974898) > 1E-8)
      okay = false;
    if(std::abs(point_values[1][0] - 1.2499951035194972) > 1E-8)
      okay = false;
    if(std::abs(point_values[1][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[1][2] - 1.2428402692519325) > 1E-8)
      okay = false;
    if(std::abs(point_values[2][0] - 1.2499864002215795) > 1E-8)
      okay = false;
    if(std::abs(point_values[2][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[2][2] - 1.2397180160697001) > 1E-8)
      okay = false;
    if(std::abs(point_values[3][0] - 1.2499739085927257) > 1E-8)
      okay = false;
    if(std::abs(point_values[3][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[3][2] - 1.2366079101139087) > 1E-8)
      okay = false;
    if(std::abs(point_values[4][0] - 1.2499576472516911) > 1E-8)
      okay = false;
    if(std::abs(point_values[4][1] - 1.25) > 1E-8)
      okay = false;
    if(std::abs(point_values[4][2] - 1.2335101392959738) > 1E-8)
      okay = false;
    break;
  }

  if (okay) {      // ndofs was 908 at the time this test was created
    printf("Success!\n");
    return ERR_SUCCESS;
  }
  else {
    printf("Failure!\n");
    return ERR_FAILURE;
  } 
}
Пример #16
0
int main(int argc, char* argv[])
{
  // Time measurement.
  TimePeriod cpu_time;
  cpu_time.tick();

  // Load the mesh.
  Mesh mesh;
  H2DReader mloader;
  mloader.load("square.mesh", &mesh);

  // Perform initial mesh refinements.
  for (int i=0; i<INIT_REF; i++) mesh.refine_all_elements();
  
  // Create an L2 space with default shapeset.
  L2Space space(&mesh, bc_types, NULL, Ord2(P_H, P_V));
  int ndof = Space::get_num_dofs(&space);
  info("ndof = %d", ndof);

  // Initialize the weak formulation.
  WeakForm wf;
  wf.add_matrix_form(callback(bilinear_form));
  wf.add_vector_form(callback(linear_form));
  wf.add_matrix_form_surf(callback(bilinear_form_boundary), H2D_DG_BOUNDARY_EDGE);
  wf.add_vector_form_surf(callback(linear_form_boundary), H2D_DG_BOUNDARY_EDGE);
  wf.add_matrix_form_surf(callback(bilinear_form_interface), H2D_DG_INNER_EDGE);

  // Initialize the FE problem.
  bool is_linear = true;
  DiscreteProblem dp(&wf, &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).
  }
    
  // Initialize the solution.
  Solution sln;
  
  // Assemble the stiffness matrix and right-hand side vector.
  info("Assembling the stiffness matrix and right-hand side vector.");
  dp.assemble(matrix, rhs);
  
  // Solve the linear system and if successful, obtain the solution.
  info("Solving the matrix problem.");
  if(solver->solve())
    Solution::vector_to_solution(solver->get_solution(), &space, &sln);
  else
    error ("Matrix solver failed.\n");
  
  // Time measurement.
  cpu_time.tick();
  
  // Clean up.
  delete solver;
  delete matrix;
  delete rhs;
  
  info("ndof = %d", ndof);
  info("Coordinate ( 0.1, 0.1) value = %lf", sln.get_pt_value(0.1, 0.1));
  info("Coordinate ( 0.3, 0.3) value = %lf", sln.get_pt_value(0.3, 0.3));
  info("Coordinate ( 0.5, 0.5) value = %lf", sln.get_pt_value(0.5, 0.5));
  info("Coordinate ( 0.7, 0.7) value = %lf", sln.get_pt_value(0.7, 0.7));

  double coor_xy[4] = {0.1, 0.3, 0.5, 0.7};
  double value[4] = {0.999885, 0.844340, 0.000000, 0.000000};
  for (int i = 0; i < 4; i++)
  {
    if ((value[i] - sln.get_pt_value(coor_xy[i], coor_xy[i])) < 1E-6)
    {
      printf("Success!\n");
    }
    else
    {
      printf("Failure!\n");
      return ERR_FAILURE;
    }
  }
  return ERR_SUCCESS;
}