Skip to content
Snippets Groups Projects
Forked from ogs / ogs
24122 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MeshGenerator.cpp 6.94 KiB
/**
 * \file
 * \author Norihiro Watanabe
 * \date   2012-08-03
 * \brief
 *
 * \copyright
 * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#include "MeshGenerator.h"
#include "Node.h"

#include "Elements/Line.h"
#include "Elements/Quad.h"
#include "Elements/Hex.h"
#include "Elements/Tri.h"

#include <vector>

namespace MeshLib
{
Mesh* MeshGenerator::generateLineMesh(
        const double length,
        const std::size_t subdivision,
        const GeoLib::Point& origin)
{
	return MeshGenerator::generateLineMesh(subdivision, length/subdivision, origin);
}

Mesh* MeshGenerator::generateLineMesh(const unsigned n_cells,
                       const double   cell_size,
                       GeoLib::Point const& origin,
					   std::string   const& mesh_name)
{
	//nodes
	const std::size_t n_nodes (n_cells + 1);
	std::vector<Node*> nodes;
	nodes.reserve(n_nodes);

	for (std::size_t i = 0; i < n_nodes; i++)
		nodes.push_back (new Node(origin[0] + cell_size * i, origin[1], origin[2], i));

	//elements
	std::vector<Element*> elements;
	elements.reserve(n_cells);

	for (std::size_t i = 0; i < n_cells; i++)
	{
		std::array<Node*, 2> element_nodes;
		element_nodes[0] = nodes[i];
		element_nodes[1] = nodes[i + 1];
		elements.push_back (new Line(element_nodes));
	}

	return new Mesh(mesh_name, nodes, elements);
}

Mesh* MeshGenerator::generateRegularQuadMesh(
        const double length,
        const std::size_t subdivision,
        const GeoLib::Point& origin)
{
	return generateRegularQuadMesh(subdivision, subdivision, length/subdivision, origin);
}
Mesh* MeshGenerator::generateRegularQuadMesh(const unsigned n_x_cells,
                              const unsigned n_y_cells,
                              const double cell_size,
                              GeoLib::Point const& origin,
                              std::string const& mesh_name)
{
	//nodes
	const unsigned n_x_nodes (n_x_cells+1);
	const unsigned n_y_nodes (n_y_cells+1);
	std::vector<Node*> nodes;
	nodes.reserve(n_x_nodes * n_y_nodes);	

	for (std::size_t i = 0; i < n_y_nodes; i++)
	{
		const double y_offset (origin[1] + cell_size * i);
		for (std::size_t j = 0; j < n_x_nodes; j++)
			nodes.push_back (new Node(origin[0] + cell_size * j, y_offset, origin[2]));
	}

	//elements
	std::vector<Element*> elements;
	elements.reserve(n_x_cells * n_y_cells);

	for (std::size_t j = 0; j < n_y_cells; j++)
	{
		const std::size_t offset_y1 = j * n_x_nodes;
		const std::size_t offset_y2 = (j + 1) * n_x_nodes;
		for (std::size_t k = 0; k < n_x_cells; k++)
		{
			std::array<Node*, 4> element_nodes;
			element_nodes[0] = nodes[offset_y1 + k];
			element_nodes[1] = nodes[offset_y1 + k + 1];
			element_nodes[2] = nodes[offset_y2 + k + 1];
			element_nodes[3] = nodes[offset_y2 + k];
			elements.push_back (new Quad(element_nodes));
		}
	}

	return new Mesh(mesh_name, nodes, elements);
}

Mesh* MeshGenerator::generateRegularHexMesh(
        const double length,
        const std::size_t subdivision,
        const GeoLib::Point& origin)
{
	return MeshGenerator::generateRegularHexMesh(subdivision, subdivision, subdivision, length/subdivision, origin);
}

Mesh* MeshGenerator::generateRegularHexMesh(const unsigned n_x_cells,
	                         const unsigned n_y_cells,
	                         const unsigned n_z_cells,
	                         const double   cell_size,
	                         GeoLib::Point const& origin,
	                         std::string   const& mesh_name)
{
	//nodes
	const unsigned n_x_nodes (n_x_cells+1);
	const unsigned n_y_nodes (n_y_cells+1);
	const unsigned n_z_nodes (n_z_cells+1);
	std::vector<Node*> nodes;
	nodes.reserve(n_x_nodes * n_y_nodes * n_z_nodes);

	for (std::size_t i = 0; i < n_z_nodes; i++)
	{
		const double z_offset (origin[2] + cell_size * i);
		for (std::size_t j = 0; j < n_y_nodes; j++)
		{
			const double y_offset (origin[1] + cell_size * j);
			for (std::size_t k = 0; k < n_x_nodes; k++)
				nodes.push_back (new Node(origin[0] + cell_size * k, y_offset, z_offset));
		}
	}

	//elements
	std::vector<Element*> elements;
	elements.reserve(n_x_cells * n_y_cells * n_z_cells);

	for (std::size_t i = 0; i < n_z_cells; i++)
	{
		const std::size_t offset_z1 = i * n_x_nodes * n_y_nodes; // bottom
		const std::size_t offset_z2 = (i + 1) * n_x_nodes * n_y_nodes; // top
		for (std::size_t j = 0; j < n_y_cells; j++)
		{
			const std::size_t offset_y1 = j * n_x_nodes;
			const std::size_t offset_y2 = (j + 1) * n_x_nodes;
			for (std::size_t k = 0; k < n_x_cells; k++)
			{
				std::array<Node*, 8> element_nodes;
				// bottom
				element_nodes[0] = nodes[offset_z1 + offset_y1 + k];
				element_nodes[1] = nodes[offset_z1 + offset_y1 + k + 1];
				element_nodes[2] = nodes[offset_z1 + offset_y2 + k + 1];
				element_nodes[3] = nodes[offset_z1 + offset_y2 + k];
				// top
				element_nodes[4] = nodes[offset_z2 + offset_y1 + k];
				element_nodes[5] = nodes[offset_z2 + offset_y1 + k + 1];
				element_nodes[6] = nodes[offset_z2 + offset_y2 + k + 1];
				element_nodes[7] = nodes[offset_z2 + offset_y2 + k];
				elements.push_back (new Hex(element_nodes));
			}
		}
	}

	return new Mesh(mesh_name, nodes, elements);
}

Mesh* MeshGenerator::generateRegularTriMesh(
        const double length,
        const std::size_t subdivision,
        const GeoLib::Point& origin)
{
	return generateRegularTriMesh(subdivision, subdivision, length/subdivision, origin);
}

Mesh* MeshGenerator::generateRegularTriMesh(const unsigned n_x_cells,
                              const unsigned n_y_cells,
                              const double cell_size,
                              GeoLib::Point const& origin,
                              std::string const& mesh_name)
{
	//nodes
	const unsigned n_x_nodes (n_x_cells+1);
	const unsigned n_y_nodes (n_y_cells+1);
	std::vector<Node*> nodes;
	nodes.reserve(n_x_nodes * n_y_nodes);

	for (std::size_t i = 0; i < n_y_nodes; i++)
	{
		const double y_offset (origin[1] + cell_size * i);
		for (std::size_t j = 0; j < n_x_nodes; j++)
			nodes.push_back (new Node(origin[0] + cell_size * j, y_offset, origin[2]));
	}

	//elements
	std::vector<Element*> elements;
	elements.reserve(n_x_cells * n_y_cells * 2);

	for (std::size_t j = 0; j < n_y_cells; j++)
	{
		const std::size_t offset_y1 = j * n_x_nodes;
		const std::size_t offset_y2 = (j + 1) * n_x_nodes;
		for (std::size_t k = 0; k < n_x_cells; k++)
		{
			std::array<Node*, 3> element1_nodes;
			element1_nodes[0] = nodes[offset_y1 + k];
			element1_nodes[1] = nodes[offset_y2 + k + 1];
			element1_nodes[2] = nodes[offset_y2 + k];
			elements.push_back (new Tri(element1_nodes));
			std::array<Node*, 3> element2_nodes;
			element2_nodes[0] = nodes[offset_y1 + k];
			element2_nodes[1] = nodes[offset_y1 + k + 1];
			element2_nodes[2] = nodes[offset_y2 + k + 1];
			elements.push_back (new Tri(element2_nodes));
		}
	}

	return new Mesh(mesh_name, nodes, elements);
}

}