Chaste Commit::1fd4e48e3990e67db148bc1bc4cf6991a0049d0c
ImmersedBoundaryHoneycombMeshGenerator.cpp
1
2/*
3
4Copyright (c) 2005-2024, University of Oxford.
5All rights reserved.
6
7University of Oxford means the Chancellor, Masters and Scholars of the
8University of Oxford, having an administrative office at Wellington
9Square, Oxford OX1 2JD, UK.
10
11This file is part of Chaste.
12
13Redistribution and use in source and binary forms, with or without
14modification, are permitted provided that the following conditions are met:
15 * Redistributions of source code must retain the above copyright notice,
16 this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright notice,
18 this list of conditions and the following disclaimer in the documentation
19 and/or other materials provided with the distribution.
20 * Neither the name of the University of Oxford nor the names of its
21 contributors may be used to endorse or promote products derived from this
22 software without specific prior written permission.
23
24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
28LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
30GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35*/
36
37#include "ImmersedBoundaryHoneycombMeshGenerator.hpp"
38
40 unsigned numElementsY,
41 unsigned numNodesPerEdge,
42 double proportionalGap,
43 double padding)
44 : mpMesh(nullptr)
45{
46 // Check for sensible input
47 assert(numElementsX > 0);
48 assert(numElementsY > 0);
49 assert(numNodesPerEdge > 2);
50 assert(proportionalGap > 0.0);
51 assert(padding > 0.0 && padding < 0.5);
52
53 // Helper vectors
54 unit_vector<double> x_unit(2,0);
55 unit_vector<double> y_unit(2,1);
56
57 std::vector<Node<2>*> nodes;
58 std::vector<ImmersedBoundaryElement<2,2>*> elements;
59
60 double width = 0.5 + 1.5 * numElementsX;
61 double height = sqrt(3.0) * numElementsY + 0.5 * sqrt(3.0) * (numElementsY > 1);
62
63 double max = width > height ? width : height;
64
65 double radius = (1.0 - 2.0 * padding) / max;
66
67 // Reset width and height to their scaled values
68 width *= radius;
69 height *= radius;
70
71 // We need to calculate the required centre of each hexagon
72 std::vector<c_vector<double, 2> > offsets(numElementsY * numElementsX);
73
74 // Specify the centre of the bottom-left most hexagon
75 c_vector<double, 2> global_offset;
76 if(width > height)
77 {
78 global_offset[0] = padding + radius;
79 global_offset[1] = 0.5 - 0.5 * height + 0.5 * radius * sqrt(3.0);
80 }
81 else
82 {
83 global_offset[0] = 0.5 - 0.5 * width + radius;
84 global_offset[1] = padding + 0.5 * sqrt(3.0) * radius;
85 }
86
87 // Calculate the centres
88 for (unsigned x = 0; x < numElementsX; x++)
89 {
90 for (unsigned y = 0; y < numElementsY; y++)
91 {
92 unsigned idx = x * numElementsY + y;
93
94 offsets[idx][0] = global_offset[0] + 1.5 * radius * x;
95 offsets[idx][1] = global_offset[1] + 0.5 * sqrt(3.0) * radius * (2.0 * y + (double)(x % 2 == 1));
96 }
97 }
98
99 // Get locations for the reference hexagon
100 std::vector<c_vector<double, 2> > node_locations = GetUnitHexagon(numNodesPerEdge);
101
102 double scale = 1.0 - proportionalGap;
103
104 // For each calculated centre, create the nodes representing each location around that hexagon
105 for (unsigned offset = 0; offset < offsets.size(); offset++)
106 {
107 std::vector<Node<2>*> nodes_this_elem;
108
109 for (unsigned location = 0; location < node_locations.size(); location++)
110 {
111 unsigned index = offset * node_locations.size() + location;
112 Node<2>* p_node = new Node<2>(index, offsets[offset] + scale * radius * node_locations[location], true);
113
114 nodes_this_elem.push_back(p_node);
115 nodes.push_back(p_node);
116 }
117
118 ImmersedBoundaryElement<2,2>* p_elem = new ImmersedBoundaryElement<2,2>(offset, nodes_this_elem);
119
120 // Set whether it's on the boundary
121 if (offset < numElementsY || // left edge
122 offset >= numElementsY * (numElementsX - 1) || // right edge
123 offset % numElementsY == 0 || // bottom edge
124 (offset + 1) % numElementsY == 0) // top edge
125 {
126 p_elem->SetIsBoundaryElement(true);
127 }
128
129 elements.push_back(p_elem);
130 }
131
132 // Create the mesh, cells, cell population, and simulation
133 mpMesh = new ImmersedBoundaryMesh<2,2>(nodes, elements);
134}
135
140
145
146std::vector<c_vector<double, 2> > ImmersedBoundaryHoneycombMeshGenerator::GetUnitHexagon(unsigned numPtsPerSide)
147{
148 std::vector<c_vector<double, 2> > locations(numPtsPerSide * 6);
149
150 // Find locations of the six vertices (and the seventh is the same as the first)
151 std::vector<c_vector<double, 2> > vertices(7);
152 double sixty_degrees = M_PI / 3.0;
153 for (unsigned vertex = 0; vertex < vertices.size(); vertex++)
154 {
155 vertices[vertex][0] = cos((double)vertex * sixty_degrees);
156 vertices[vertex][1] = sin((double)vertex * sixty_degrees);
157 }
158
159 // Between each pair of vertices, fill in the specified number of locations evenly spaced along the edge
160 for (unsigned vertex = 0; vertex < 6; vertex++)
161 {
162 c_vector<double, 2> this_vertex = vertices[vertex];
163 c_vector<double, 2> next_vertex = vertices[vertex + 1];
164 c_vector<double, 2> vec_between = next_vertex - this_vertex;
165
166 for (unsigned i = 0; i < numPtsPerSide; i++)
167 {
168 locations[vertex * numPtsPerSide + i] = this_vertex + i * vec_between / (double)numPtsPerSide;
169 }
170 }
171 return locations;
172}
void SetIsBoundaryElement(bool isBoundaryElement)
std::vector< c_vector< double, 2 > > GetUnitHexagon(unsigned numPtsPerSide)
Definition Node.hpp:59