libMesh
Loading...
Searching...
No Matches
Functions
embedding.C File Reference

Go to the source code of this file.

Functions

void usage_error (const char *progname)
 
template<typename T >
assert_argument (GetPot &cl, const std::string &argname, const char *progname, const T &defaultarg)
 
int main (int argc, char **argv)
 

Function Documentation

◆ assert_argument()

template<typename T >
T assert_argument ( GetPot &  cl,
const std::string &  argname,
const char *  progname,
const T &  defaultarg 
)

Definition at line 55 of file embedding.C.

59{
60 if (!cl.search(argname))
61 {
62 libMesh::err << ("No " + argname + " argument found!") << std::endl;
63 usage_error(progname);
64 }
65 return cl.next(defaultarg);
66}
void usage_error(const char *progname)
Definition embedding.C:41
OStreamProxy err

References libMesh::err, and usage_error().

Referenced by main().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 70 of file embedding.C.

71{
72 LibMeshInit init(argc, argv);
73
74 GetPot cl(argc, argv);
75
76 const std::string elem_type_string =
77 assert_argument(cl, "--elem", argv[0], std::string(""));
78
79 const int childnum =
80 assert_argument(cl, "--childnum", argv[0], 0);
81
82 const int denominator =
83 assert_argument(cl, "--denominator", argv[0], 1);
84
85 const bool diff = cl.search("--diff");
86
87 const ElemType elem_type =
88 Utility::string_to_enum<ElemType>(elem_type_string);
89
90 // Getting an embedding matrix isn't a static function, thanks to
91 // situations like Tet diagonal selection
92 std::unique_ptr<Elem> elem = Elem::build(elem_type);
93
94 const Elem & ref = ReferenceElem::get(elem_type);
95
96 // Lagrange FE for nodal calculations
97 FEType fe_type(elem->default_order());
98
99 const unsigned int n_nodes = FEInterface::n_dofs(fe_type, elem.get());
100 libmesh_error_msg_if(n_nodes != elem->n_nodes(), "Bad FEInterface value?");
101
102 std::vector<Node> nodes(n_nodes);
103
104 // Get the child vertex positions from childnum; those are easy.
105 for (auto v : make_range(elem->n_vertices()))
106 {
107 for (auto n : make_range(n_nodes))
108 {
109 const Real embed = ref.embedding_matrix(childnum, v, n);
110 if (embed == 1.0)
111 {
112 nodes[v] = ref.point(n);
113 elem->set_node(v, &nodes[v]);
114 }
115 else if (embed != 0.0)
116 libmesh_error_msg("Found fractional embedding on vertex!?");
117 }
118 }
119
120 // Now figure out the others
121 for (auto n : make_range(elem->n_vertices(), n_nodes))
122 {
123 const auto & pbns = ref.parent_bracketing_nodes(childnum, n);
124 if (pbns.empty())
125 libmesh_error();
126
127 for (auto pbn : pbns)
128 nodes[n] += (ref.point(pbn.first) + ref.point(pbn.second))/2;
129 nodes[n] /= pbns.size();
130 elem->set_node(n, &nodes[n]);
131 }
132
133 const unsigned int denomdigits = std::ceil(std::log10(denominator));
134 const unsigned int spacing = denomdigits*2+3;
135
136 std::cout.precision(17);
137
138 std::cout << " // embedding matrix for child " << childnum << '\n';
139 std::cout << " {\n";
140 std::cout << " //";
141 for (auto i : make_range(n_nodes))
142 {
143 const unsigned int indexdigits =
144 std::ceil(std::log10(i));
145 const int padding = spacing-indexdigits-2*(i==0);
146 for (int k=0; k < padding; ++k)
147 std::cout << ' ';
148 std::cout << i;
149 if (i+1 == n_nodes)
150 std::cout << '\n';
151 else
152 std::cout << ',';
153 }
154
155 for (auto i : make_range(n_nodes))
156 {
157 const Point & pt = elem->point(i);
158 std::cout << " {";
159 for (auto j : make_range(n_nodes))
160 {
161 Real shape = FEInterface::shape(fe_type, elem.get(), j, pt);
162
163 // Don't print -0 or 1e-17; we don't tolerate FP error at 0
164 if (std::abs(shape) < TOLERANCE*std::sqrt(TOLERANCE))
165 shape = 0;
166
167 const Real embed = ref.embedding_matrix(childnum, i, j);
168 if (diff &&
169 std::abs(shape - embed) < TOLERANCE*std::sqrt(TOLERANCE))
170 {
171 for (unsigned int k=0; k != spacing; ++k)
172 std::cout << '+';
173 if (j+1 != n_nodes)
174 std::cout << ',';
175 }
176 else
177 {
178 int oldnumerator = int(std::round(shape*denominator));
179 int newnumerator = oldnumerator;
180 int newdenominator = denominator;
181
182 if (std::abs(oldnumerator-shape*denominator) < TOLERANCE*sqrt(TOLERANCE))
183 {
184 int the_gcd = std::gcd(newnumerator, newdenominator);
185 newnumerator /= the_gcd;
186 newdenominator /= the_gcd;
187 }
188
189 const unsigned int newdenomdigits =
190 std::ceil(std::log10(newdenominator));
191 std::ostringstream ostr;
192 ostr << (shape*newdenominator);
193 const int padding =
194 (shape != 0.0 && newdenominator != 1) ?
195 int(spacing)-newdenomdigits-2-ostr.str().size() :
196 int(spacing)-ostr.str().size();
197 for (int k=0; k < padding; ++k)
198 std::cout << ' ';
199 std::cout << ostr.str();
200 if (shape != 0.0 && newdenominator != 1)
201 {
202 if (1 << (int)std::round(std::log2(newdenominator)) ==
203 newdenominator)
204 std::cout << "/" << newdenominator << '.';
205 // If we don't have a power of 2 we need to make
206 // sure we're dividing at might-exceed-double Real
207 // precision
208 else
209 std::cout << "/r" << newdenominator;
210 }
211 if (j+1 != n_nodes)
212 std::cout << ',';
213 }
214 }
215
216 if (i+1 == n_nodes)
217 std::cout << "} ";
218 else
219 std::cout << "}, ";
220
221 std::cout << "// " << i << '\n';
222 }
223 std::cout << " },\n";
224
225 return 0;
226}
void ErrorVector unsigned int
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual const std::vector< std::pair< unsigned char, unsigned char > > & parent_bracketing_nodes(unsigned int c, unsigned int n) const
Definition elem.C:2481
const Point & point(const unsigned int i) const
Definition elem.h:2462
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition elem.C:442
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition fe_type.h:197
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition libmesh.h:92
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
T assert_argument(GetPot &cl, const std::string &argname, const char *progname, const T &defaultarg)
Definition embedding.C:55
const Elem & get(const ElemType type_in)
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
ElemType
Defines an enum for geometric element types.
static constexpr Real TOLERANCE
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition int_range.h:176
const dof_id_type n_nodes
Definition tecplot_io.C:67

References assert_argument(), libMesh::Elem::build(), libMesh::Elem::embedding_matrix(), libMesh::ReferenceElem::get(), int, main(), libMesh::make_range(), libMesh::FEInterface::n_dofs(), n_nodes, libMesh::Elem::parent_bracketing_nodes(), libMesh::Elem::point(), libMesh::Real, libMesh::FEInterface::shape(), and libMesh::TOLERANCE.

◆ usage_error()

void usage_error ( const char *  progname)

Definition at line 41 of file embedding.C.

42{
43 libMesh::out << "Options: " << progname << '\n'
44 << " --elem type elem type (e.g. TET14)\n"
45 << " --childnum num child number\n"
46 << " --denominator num denominator to use\n"
47 << " --diff only output diffs from existing\n"
48 << std::endl;
49
50 exit(1);
51}
OStreamProxy out

References libMesh::out.

Referenced by assert_argument().