Alamo
PointList.H
Go to the documentation of this file.
1//
2// Fill a domain based on a list of points to form a closed 2D shape.
3// The distance from each point to the nearest edge is found and an error function is then used to compute
4// the value of phi between 0 (outside) and 1 (inside) the domain. Only works in 2 dimensions for a single closed polgyon
5
6#ifndef IC_POINTLIST_H_
7#define IC_POINTLIST_H_
8
9#include "Set/Set.H"
10#include "IC/IC.H"
11#include "Util/Util.H"
12using namespace std;
13#include <iostream>
14#include <vector>
15#include <algorithm>
16#include <iterator>
17#include <mpi.h>
18#include "IO/ParmParse.H"
19
20namespace IC
21{
22class PointList : public IC<Set::Scalar>
23{
24public:
25 static constexpr const char* name = "pointlist";
26
27 enum Type
28 {
30 Values
31 };
32
33 PointList(amrex::Vector<amrex::Geometry>& _geom) : IC(_geom) {}
34
35 PointList(amrex::Vector<amrex::Geometry>& _geom, IO::ParmParse& pp, std::string name) : IC(_geom)
36 {
37 pp.queryclass(name, *this);
38 }
39 void Define() {
40
41 };
42
43 void Add(const int& lev, Set::Field<Set::Scalar>& a_phi, Set::Scalar)
44 {
45 for (amrex::MFIter mfi(*a_phi[lev], amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
46 {
47 if (AMREX_SPACEDIM != 2)
48 {
49 amrex::Abort("This code only supports 2D (AMREX_SPACEDIM must be 2)");
50 }
51
52 amrex::Box bx;
53 amrex::IndexType type = a_phi[lev]->ixType();
54 if (type == amrex::IndexType::TheCellType()) bx = mfi.growntilebox();
55 else if (type == amrex::IndexType::TheNodeType()) bx = mfi.grownnodaltilebox();
56 else Util::Abort(INFO, "Unkonwn index type");
57 amrex::Array4<Set::Scalar> const& phi = a_phi[lev]->array(mfi);
58
59 for (unsigned int n = 0; n < X.size(); n++)
60 {
61 for (unsigned int n = 0; n < X.size(); n++)
62 {
63 double x = X[n][0];
64 double y = X[n][1];
65
66 double cx = rotation.center[0];
67 double cy = rotation.center[1];
68
69 double theta = rotation.angle;
70
71 double cos_t = std::cos(theta);
72 double sin_t = std::sin(theta);
73
74 double x_shifted = x - cx;
75 double y_shifted = y - cy;
76
77 X[n][0] = cx + x_shifted * cos_t - y_shifted * sin_t;
78 X[n][1] = cy + x_shifted * sin_t + y_shifted * cos_t;
79 }
80 }
81
82 if (X.back() != X.front())
83 // The first and last point must match, if they do not add another point to the end
84 {
85 X.push_back(X.front());
86 }
87
88 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(int i, int j, int k)
89 {
90 Set::Vector x = Set::Position(i, j, k, geom[lev], type);
91 Set::Scalar x_cross;
92 Set::Scalar min_dist_to_edge = std::numeric_limits<Set::Scalar>::max(); // Mininmum distance from point to nearest edge
93 Set::Scalar dist_to_edge; // Distance from point to nearest edge
94 Set::Scalar x1;
95 Set::Scalar y1;
96 Set::Scalar x2;
97 Set::Scalar y2;
98 int num_cross = 0;
99
100 Set::Scalar px;
101 Set::Scalar py;
102 Set::Scalar dx;
103 Set::Scalar dy;
104 Set::Scalar len2;
106 Set::Vector x_int; // x and y position of the intercept of the mesh point and the edge, assuming edge is infinite
107
108 for (unsigned int n = 0; n < X.size()-1; n++)
109 {
110
111 x1 = X[n](0);
112 y1 = X[n](1);
113 x2 = X[n+1](0);
114 y2 = X[n+1](1);
115
116 if ((y1 > x(1)) != (y2 > x(1)))
117 {
118 x_cross = x1 + (x(1) - y1) * (x2 - x1) / (y2 - y1);
119
120 if (x_cross > x(0))
121 num_cross++;
122 }
123
124 // Computes the closest point on a line segment (X[n] → X[n+1]) to a query point x,
125 // using vector projection onto the segment.
126 //
127 // Let A = X[n], B = X[n+1], and P = x.
128 //
129 // The parameter t is the normalized projection of P onto the infinite line AB:
130 //
131 // t = ((P - A) · (B - A)) / |B - A|^2
132 //
133 // If t ∈ [0, 1], the perpendicular projection lies within the segment.
134 // If t < 0, the closest point is A.
135 // If t > 1, the closest point is B.
136 //
137 // The resulting closest point x_int is then used to compute the Euclidean
138 // distance from P to the segment, and the minimum distance over all edges is tracked.
139 px = x(0);
140 py = x(1);
141 dx = x2 - x1;
142 dy = y2 - y1;
143 len2 = dx*dx + dy*dy;
144 t = ((px - x1)*dx + (py - y1)*dy) / len2;
145
146 if (t < 0.0)
147 {
148 x_int(0) = x1;
149 x_int(1) = y1;
150 }
151 else if (t > 1.0)
152 {
153 x_int(0) = x2;
154 x_int(1) = y2;
155 }
156 else
157 {
158 x_int(0) = x1 + t*dx;
159 x_int(1) = y1 + t*dy;
160 }
161
162 dist_to_edge = dist(x(0), x(1), x_int(0), x_int(1));
163 min_dist_to_edge = std::min(min_dist_to_edge, dist_to_edge);
164
165 }
166 if (num_cross % 2 == 0)
167 {
168 min_dist_to_edge = 1*min_dist_to_edge; // If the number of crossings is even, the point is inside the shape
169 } else
170 {
171 min_dist_to_edge = -1*min_dist_to_edge;
172 }
173
174 phi(i,j,k) = 0.5 * (1.0 - std::tanh(min_dist_to_edge /(std::sqrt(2.0) * eps)));
175
176 if (invert) {
177 phi(i,j,k) = 1 - phi(i,j,k);
178 }
179
180 });
181 }
182 }
183
184 static void Parse(PointList& value, IO::ParmParse& pp)
185 {
186 std::string filename;
187 int verbose = 0;
188 // Diffuseness of the solid boundary
189 pp.query_default("eps", value.eps, "0.0", Unit::Length());
190
191 pp.forbid("filename", "use file.name instead");
192 // Location of .xy file
193 pp.query_file("file.name", filename);
194
195 // Verbosity (used in parser only)
196 pp.query_default("verbose", verbose, 0);
197
198 // Unitless coordinate multiplier
199 pp.query_default("mult",value.mult, "1.0", Unit::Less());
200
201 // Whether to invert (make IC 1 outside of solid instead of inside solid)
202 pp.query_default("invert",value.invert,false);
203
204 // X-offset
205 pp.queryarr_default("x0",value.x0,"0.0 0.0 0.0", Unit::Length());
206
207 if (pp.contains("x0"))
208 pp_queryarr("x0",value.x0); // Coordinate offset
209
210 // Center of rigid-body rotation
211 pp.queryarr_default("rotation.center",value.rotation.center,"0.0 0.0 0.0", Unit::Length());
212
213 // Amount of rotation about rotation center (clockwise)
214 pp.query_default("rotation.angle",value.rotation.angle,"0.0", Unit::Angle());
215
216
217 Unit unit = Unit::Length();
218 // Units of length in the file
219 pp.queryunit("file.unit",unit);
221 "Unit must be of type length but got unit ",unit.normalized_unitstring());
222
223 std::ifstream datafile(filename);
224 std::string line;
225 if (datafile.is_open())
226 {
227 value.X.clear();
228
229 while (getline(datafile, line))
230 {
231 std::istringstream in(line);
232
233 std::string strx, stry, strz, strR;
234 in >> strx >> stry >> strz >> strR;
235
236 Set::Scalar x = (std::stod(strx) * unit).normalized_value();
237 Set::Scalar y = (std::stod(stry) * unit).normalized_value();
238 #if AMREX_SPACEDIM > 2
239 Set::Scalar z = (std::stod(strz) * unit).normalized_value();
240 #endif
241
242 Set::Vector X(AMREX_D_DECL(x,y,z));
243 X = value.x0 + value.mult*X;
244
245 value.X.push_back(X);
246 if (verbose > 0)
247 Util::Message(INFO, "x=", value.X.back().transpose());
248 }
249 datafile.close();
250 }
251 else
252 {
253 Util::Abort(INFO, "Unable to open file ", filename);
254 }
255 }
256
257private:
258 std::vector<Set::Vector> X; // Big X is a vector of vectors of each coordinate read into the file
261 Set::Vector x0 = Set::Vector::Zero();
262 bool invert = false;
263
264 struct{
268
269 double dist(double x1, double y1, double x2, double y2)
270 {
271 // Find distance between 2 points
272 double dx = x2 - x1;
273 double dy = y2 - y1;
274
275 return std::sqrt(dx*dx + dy*dy);
276 }
277};
278}
279#endif
std::time_t t
#define pp_queryarr(...)
Definition ParmParse.H:105
#define TEST(x)
Definition Util.H:25
#define INFO
Definition Util.H:24
amrex::Vector< amrex::Geometry > & geom
Definition IC.H:61
Set::Vector x0
Definition PointList.H:261
Set::Scalar mult
Definition PointList.H:260
double dist(double x1, double y1, double x2, double y2)
Definition PointList.H:269
Set::Scalar angle
Definition PointList.H:266
Set::Scalar eps
Definition PointList.H:259
PointList(amrex::Vector< amrex::Geometry > &_geom, IO::ParmParse &pp, std::string name)
Definition PointList.H:35
void Define()
Definition PointList.H:39
void Add(const int &lev, Set::Field< Set::Scalar > &a_phi, Set::Scalar)
Definition PointList.H:43
std::vector< Set::Vector > X
Definition PointList.H:258
static void Parse(PointList &value, IO::ParmParse &pp)
Definition PointList.H:184
Set::Vector center
Definition PointList.H:265
PointList(amrex::Vector< amrex::Geometry > &_geom)
Definition PointList.H:33
static constexpr const char * name
Definition PointList.H:25
struct IC::PointList::@0 rotation
bool contains(std::string name)
Definition ParmParse.H:173
int queryunit(std::string name, Unit &value)
Definition ParmParse.H:192
int queryarr_default(std::string name, std::vector< std::string > &value, std::vector< std::string > defaultvalue)
Definition ParmParse.H:660
void forbid(std::string name, std::string explanation)
Definition ParmParse.H:160
int query_file(std::string name, std::string &value, bool copyfile, bool checkfile)
Definition ParmParse.H:486
void queryclass(std::string name, T *value)
Definition ParmParse.H:960
int query_default(std::string name, T &value, T defaultvalue)
Definition ParmParse.H:293
Initialize a spherical inclusion.
Definition BMP.H:20
amrex::Real Scalar
Definition Base.H:18
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:19
AMREX_FORCE_INLINE Vector Position(const int &i, const int &j, const int &k, const amrex::Geometry &geom, const amrex::IndexType &ixType)
Definition Base.H:120
AMREX_FORCE_INLINE void AssertException(std::string file, std::string func, int line, std::string smt, bool pass, Args const &... args)
Definition Util.H:254
void Abort(const char *msg)
Definition Util.cpp:268
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:129
Definition Unit.H:21
bool isType(const Unit &test) const
Definition Unit.H:425
std::string normalized_unitstring() const
Definition Unit.H:515
static Unit Angle()
Definition Unit.H:206
static Unit Length()
Definition Unit.H:198
static Unit Less()
Definition Unit.H:197