libMesh
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.

References libMesh::err, and usage_error().

Referenced by main().

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 }
OStreamProxy err
void usage_error(const char *progname)
Definition: embedding.C:41

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 70 of file embedding.C.

References assert_argument(), libMesh::Elem::build(), libMesh::Elem::embedding_matrix(), libMesh::ReferenceElem::get(), libMesh::TriangleWrapper::init(), int, 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.

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 }
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
Definition: fe_type.h:196
ElemType
Defines an enum for geometric element types.
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
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
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
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: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)

◆ usage_error()

void usage_error ( const char *  progname)

Definition at line 41 of file embedding.C.

References libMesh::out.

Referenced by assert_argument().

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