MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
sbm_aux.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "mfem.hpp"
13
14using namespace std;
15using namespace mfem;
16
18{
19 Vector v0 = p1;
20 Vector v1 = p2; v1 -=p1;
21 Vector v2 = p3; v2 -=p1;
22 real_t p, q;
23 p = ((px(0)*v2(1)-px(1)*v2(0))-(v0(0)*v2(1)-v0(1)*v2(0))) /
24 (v1(0)*v2(1)-v1(1)*v2(0));
25 q = -((px(0)*v1(1)-px(1)*v1(0))-(v0(0)*v1(1)-v0(1)*v1(0))) /
26 (v1(0)*v2(1)-v1(1)*v2(0));
27
28 return (p > 0 && q > 0 && 1-p-q > 0) ? -1.0 : 1.0;
29}
30
31// 1 is inside the doughnut, -1 is outside.
33{
34 // map [0,1] to [-1,1].
35 real_t x = 2*coord(0)-1.0, y = 2*coord(1)-1.0, z = 2*coord(2)-1.0;
36
37 bool doughnut;
38 const real_t R = 0.8, r = 0.15;
39 const real_t t = R - std::sqrt(x*x + y*y);
40 doughnut = t*t + z*z - r*r <= 0;
41
42 bool cheese;
43 x = 3.0*x, y = 3.0*y, z = 3.0*z;
44 cheese = (x*x + y*y - 4.0) * (x*x + y*y - 4.0) +
45 (z*z - 1.0) * (z*z - 1.0) +
46 (y*y + z*z - 4.0) * (y*y + z*z - 4.0) +
47 (x*x - 1.0) * (x*x - 1.0) +
48 (z*z + x*x - 4.0) * (z*z + x*x - 4.0) +
49 (y*y - 1.0) * (y*y - 1.0) - 15.0 <= 0.0;
50
51 return (doughnut || cheese) ? 1.0 : -1.0;
52}
53
54/// Analytic distance to the 0 level set. Positive value if the point is inside
55/// the domain, and negative value if outside.
56real_t dist_value(const Vector &x, const int type)
57{
58 if (type == 1 || type == 2) // circle of radius 0.2 - centered at 0.5, 0.5
59 {
60 const real_t ring_radius = 0.2;
61 Vector xc(x.Size());
62 xc = 0.5;
63 xc -= x;
64 return xc.Norml2() - ring_radius; // positive is the domain
65 }
66 else if (type == 3) // walls at y = 0.0
67 {
68 return x(1);
69 }
70 else if (type == 4)
71 {
72 const int num_circ = 3;
73 real_t rad[num_circ] = {0.3, 0.15, 0.2};
74 real_t c[num_circ][2] = { {0.6, 0.6}, {0.3, 0.3}, {0.25, 0.75} };
75
76 const real_t xc = x(0), yc = x(1);
77
78 // circle 0
79 real_t r0 = (xc-c[0][0])*(xc-c[0][0]) + (yc-c[0][1])*(yc-c[0][1]);
80 r0 = (r0 > 0) ? std::sqrt(r0) : 0.0;
81 if (r0 <= 0.2) { return -1.0; }
82
83 for (int i = 0; i < num_circ; i++)
84 {
85 real_t r = (xc-c[i][0])*(xc-c[i][0]) + (yc-c[i][1])*(yc-c[i][1]);
86 r = (r > 0) ? std::sqrt(r) : 0.0;
87 if (r <= rad[i]) { return 1.0; }
88 }
89
90 // rectangle 1
91 if (0.7 <= xc && xc <= 0.8 && 0.1 <= yc && yc <= 0.8) { return 1.0; }
92
93 // rectangle 2
94 if (0.3 <= xc && xc <= 0.8 && 0.15 <= yc && yc <= 0.2) { return 1.0; }
95 return -1.0;
96 }
97 else if (type == 5) // square of side 0.2 centered at 0.75, 0.25
98 {
99 real_t square_side = 0.2;
100 Vector xc(x.Size());
101 xc = 0.75; xc(1) = 0.25;
102 xc -= x;
103 if (abs(xc(0)) > 0.5*square_side || abs(xc(1)) > 0.5*square_side)
104 {
105 return 1.0;
106 }
107 else
108 {
109 return -1.0;
110 }
111 return 0.0;
112 }
113 else if (type == 6) // Triangle
114 {
115 Vector p1(x.Size()), p2(x.Size()), p3(x.Size());
116 p1(0) = 0.25; p1(1) = 0.4;
117 p2(0) = 0.1; p2(1) = 0.1;
118 p3(0) = 0.4; p3(1) = 0.1;
119 return point_inside_trigon(x, p1, p2, p3);
120 }
121 else if (type == 7) // circle of radius 0.2 - centered at 0.5, 0.6
122 {
123 Vector xc(x.Size());
124 xc = 0.5; xc(1) = 0.6;
125 xc -= x;
126 return xc.Norml2() - 0.2;
127 }
128 else if (type == 8) { return doughnut_cheese(x); }
129 else
130 {
131 MFEM_ABORT(" Function type not implement yet.");
132 }
133 return 0.;
134}
135
136/// Level set coefficient: +1 inside the true domain, -1 outside.
138{
139private:
140 int type;
141
142public:
144 : Coefficient(), type(type_) { }
145
147 {
148 Vector x(3);
149 T.Transform(ip, x);
150 real_t dist = dist_value(x, type);
151 return (dist >= 0.0) ? 1.0 : -1.0;
152 }
153};
154
155/// Combination of level sets: +1 inside the true domain, -1 outside.
157{
158private:
160
161public:
163
166
167 int GetNLevelSets() { return dls.Size(); }
168
170 {
171 MFEM_VERIFY(dls.Size() > 0,
172 "Add at least 1 Dist_level_Set_Coefficient to the Combo.");
173 real_t dist = dls[0]->Eval(T, ip);
174 for (int j = 1; j < dls.Size(); j++)
175 {
176 dist = min(dist, dls[j]->Eval(T, ip));
177 }
178 return (dist >= 0.0) ? 1.0 : -1.0;
179 }
180};
181
182/// Distance vector to the zero level-set.
184{
185private:
186 int type;
187
188public:
189 Dist_Vector_Coefficient(int dim_, int type_)
190 : VectorCoefficient(dim_), type(type_) { }
191
193
195 const IntegrationPoint &ip)
196 {
197 Vector x;
198 T.Transform(ip, x);
199 const int dim = x.Size();
200 p.SetSize(dim);
201 if (type == 1 || type == 2)
202 {
203 real_t dist0 = dist_value(x, type);
204 for (int i = 0; i < dim; i++) { p(i) = 0.5 - x(i); }
205 real_t length = p.Norml2();
206 p *= dist0/length;
207 }
208 else if (type == 3)
209 {
210 real_t dist0 = dist_value(x, type);
211 p(0) = 0.;
212 p(1) = -dist0;
213 }
214 }
215};
216
217/// Boundary conditions - Dirichlet
219{
220 return 0.0;
221}
222
224{
225 real_t xy_p = 2.; // exponent for level set 2 where u = x^p+y^p;
226 return pow(x(0), xy_p) + pow(x(1), xy_p);
227}
228
230{
231 return 1./(M_PI*M_PI)*std::sin(M_PI*x(0)*x(1));
232}
233
234/// Boundary conditions - Neumann
235/// Normal vector for level_set_type = 1. Circle centered at [0.5 , 0.5]
237{
238 p.SetSize(x.Size());
239 p(0) = x(0)-0.5;
240 p(1) = x(1)-0.5; // center of circle at [0.5, 0.5]
241 p /= p.Norml2();
242 p *= -1;
243}
244
245/// Normal vector for level_set_type = 7. Circle centered at [0.5 , 0.6]
247{
248 p.SetSize(x.Size());
249 p(0) = x(0)-0.5;
250 p(1) = x(1)-0.6; // center of circle at [0.5, 0.6]
251 p /= p.Norml2();
252 p *= -1;
253}
254
255/// Neumann condition for exponent based solution
257{
258 real_t xy_p = 2;
259 Vector gradient(2);
260 gradient(0) = xy_p*x(0);
261 gradient(1) = xy_p*x(1);
262 Vector normal(2);
263 normal_vector_1(x, normal);
264 return 1.0*(gradient*normal);
265}
266
267/// `f` for the Poisson problem (-nabla^2 u = f).
269{
270 return 1;
271}
272
274{
275 real_t xy_p = 2.; // exponent for level set 2 where u = x^p+y^p;
276 real_t coeff = std::max(xy_p*(xy_p-1), real_t(1));
277 real_t expon = std::max(real_t(0), xy_p-2);
278 if (xy_p == 1)
279 {
280 return 0.;
281 }
282 else
283 {
284 return -coeff*std::pow(x(0), expon) - coeff*std::pow(x(1), expon);
285 }
286}
287
289{
290 return std::sin(M_PI*x(0)*x(1))*(x(0)*x(0)+x(1)*x(1));
291}
Combination of level sets: +1 inside the true domain, -1 outside.
Definition sbm_aux.hpp:157
void Add_Level_Set_Coefficient(Dist_Level_Set_Coefficient &dls_)
Definition sbm_aux.hpp:164
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)
Evaluate the coefficient in the element described by T at the point ip.
Definition sbm_aux.hpp:169
Level set coefficient: +1 inside the true domain, -1 outside.
Definition sbm_aux.hpp:138
virtual real_t Eval(ElementTransformation &T, const IntegrationPoint &ip)
Evaluate the coefficient in the element described by T at the point ip.
Definition sbm_aux.hpp:146
Dist_Level_Set_Coefficient(int type_)
Definition sbm_aux.hpp:143
Distance vector to the zero level-set.
Definition sbm_aux.hpp:184
virtual void Eval(Vector &p, ElementTransformation &T, const IntegrationPoint &ip)
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Definition sbm_aux.hpp:194
Dist_Vector_Coefficient(int dim_, int type_)
Definition sbm_aux.hpp:189
int Size() const
Return the logical size of the array.
Definition array.hpp:144
int Append(const T &el)
Append element 'el' to array, resize if necessary.
Definition array.hpp:769
Base class Coefficients that optionally depend on space and time. These are used by the BilinearFormI...
virtual void Transform(const IntegrationPoint &, Vector &)=0
Transform integration point from reference coordinates to physical coordinates and store them in the ...
Class for integration point with weight.
Definition intrules.hpp:35
Base class for vector Coefficients that optionally depend on time and space.
virtual void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip)=0
Evaluate the vector coefficient in the element described by T at the point ip, storing the result in ...
Vector data type.
Definition vector.hpp:80
real_t Norml2() const
Returns the l2 norm of the vector.
Definition vector.cpp:832
int Size() const
Returns the size of the vector.
Definition vector.hpp:218
int dim
Definition ex24.cpp:53
float real_t
Definition config.hpp:43
real_t p(const Vector &x, real_t t)
RefCoord t[3]
real_t rhs_fun_xy_exponent(const Vector &x)
Definition sbm_aux.hpp:273
real_t dirichlet_velocity_xy_exponent(const Vector &x)
Definition sbm_aux.hpp:223
real_t dirichlet_velocity_xy_sinusoidal(const Vector &x)
Definition sbm_aux.hpp:229
real_t rhs_fun_xy_sinusoidal(const Vector &x)
Definition sbm_aux.hpp:288
real_t point_inside_trigon(const Vector px, Vector p1, Vector p2, Vector p3)
Definition sbm_aux.hpp:17
real_t doughnut_cheese(const Vector &coord)
Definition sbm_aux.hpp:32
real_t homogeneous(const Vector &x)
Boundary conditions - Dirichlet.
Definition sbm_aux.hpp:218
real_t traction_xy_exponent(const Vector &x)
Neumann condition for exponent based solution.
Definition sbm_aux.hpp:256
void normal_vector_1(const Vector &x, Vector &p)
Definition sbm_aux.hpp:236
real_t dist_value(const Vector &x, const int type)
Definition sbm_aux.hpp:56
real_t rhs_fun_circle(const Vector &x)
f for the Poisson problem (-nabla^2 u = f).
Definition sbm_aux.hpp:268
void normal_vector_2(const Vector &x, Vector &p)
Normal vector for level_set_type = 7. Circle centered at [0.5 , 0.6].
Definition sbm_aux.hpp:246