Loading [MathJax]/extensions/tex2jax.js
libMesh
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
embedding.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 // Open the input mesh and corresponding solution file named in command line
20 // arguments, open the output mesh, project that solution onto the
21 // output mesh, and write a corresponding output solution file.
22 
23 // libMesh includes
24 #include "libmesh/elem.h"
25 #include "libmesh/fe_interface.h"
26 #include "libmesh/fe_type.h"
27 #include "libmesh/getpot.h"
28 #include "libmesh/int_range.h"
29 #include "libmesh/libmesh.h"
30 #include "libmesh/reference_elem.h"
31 #include "libmesh/string_to_enum.h"
32 #include "libmesh/point.h"
33 
34 // C++ includes
35 #include <numeric> // gcd
36 
37 using namespace libMesh;
38 
39 
40 // If there's a missing input argument, then print a help message
41 void usage_error(const char * progname)
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 }
52 
53 // Get an input argument, or print a help message if it's missing
54 template <typename T>
55 T assert_argument (GetPot & cl,
56  const std::string & argname,
57  const char * progname,
58  const T & defaultarg)
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 }
67 
68 
69 #ifdef LIBMESH_ENABLE_AMR
70 int main(int argc, char ** argv)
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 }
227 #else
228 int main (int, char **)
229 {
230  std::cout << "This libMesh was built with --disable-amr" << std::endl;
231  return 1;
232 }
233 #endif // ENABLE_AMR
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
OStreamProxy err
ElemType
Defines an enum for geometric element types.
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:355
void usage_error(const char *progname)
Definition: embedding.C:41
static constexpr Real TOLERANCE
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
The LibMeshInit class, when constructed, initializes the dependent libraries (e.g.
Definition: libmesh.h:90
The libMesh namespace provides an interface to certain functionality in the library.
virtual Real embedding_matrix(const unsigned int child_num, const unsigned int child_node_num, const unsigned int parent_node_num) const =0
const dof_id_type n_nodes
Definition: tecplot_io.C:67
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
Definition: fe_interface.C:760
static std::unique_ptr< Elem > build(const ElemType type, Elem *p=nullptr)
Definition: elem.C:444
void init(triangulateio &t)
Initializes the fields of t to nullptr/0 as necessary.
T assert_argument(GetPot &cl, const std::string &argname, const char *progname, const T &defaultarg)
Definition: embedding.C:55
int main(int argc, char **argv)
Definition: embedding.C:70
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OStreamProxy out
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:140
virtual const std::vector< std::pair< unsigned char, unsigned char > > & parent_bracketing_nodes(unsigned int c, unsigned int n) const
Definition: elem.C:2454
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
const Point & point(const unsigned int i) const
Definition: elem.h:2453
void ErrorVector unsigned int
Definition: adjoints_ex3.C:360
const Elem & get(const ElemType type_in)