Fluid structure interaction suite
components.cc
Go to the documentation of this file.
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2022 by Luca Heltai
4 //
5 // This file is part of the FSI-suite platform, based on the deal.II library.
6 //
7 // The FSI-suite platform is free software; you can use it, redistribute it,
8 // and/or modify it under the terms of the GNU Lesser General Public License as
9 // published by the Free Software Foundation; either version 3.0 of the License,
10 // or (at your option) any later version. The full text of the license can be
11 // found in the file LICENSE at the top level of the FSI-suite platform
12 // distribution.
13 //
14 // ---------------------------------------------------------------------
15 
17 
18 #include <deal.II/base/patterns.h>
19 
20 #include <numeric>
21 using namespace dealii;
22 
23 namespace ParsedTools
24 {
29  namespace Components
30  {
31  unsigned int
32  n_components(const std::string &component_names)
33  {
34  return Utilities::split_string_list(component_names).size();
35  }
36 
37 
38 
39  std::string
40  blocks_to_names(const std::vector<std::string> &components,
41  const std::vector<unsigned int> &multiplicities)
42  {
43  AssertDimension(components.size(), multiplicities.size());
44  std::vector<std::string> all_components;
45  for (unsigned int i = 0; i < components.size(); ++i)
46  {
47  for (unsigned int j = 0; j < multiplicities[i]; ++j)
48  all_components.push_back(components[i]);
49  }
50  return Patterns::Tools::to_string(all_components);
51  }
52 
53 
54 
55  std::pair<std::vector<std::string>, std::vector<unsigned int>>
56  names_to_blocks(const std::string &component_names)
57  {
58  auto components = Utilities::split_string_list(component_names);
59  auto blocks = components;
60  auto last = std::unique(blocks.begin(), blocks.end());
61  blocks.erase(last, blocks.end());
62  std::vector<unsigned int> multiplicities;
63  for (const auto &c : blocks)
64  multiplicities.push_back(
65  std::count(components.begin(), components.end(), c));
66 
67  AssertDimension(blocks.size(), multiplicities.size());
68  return std::make_pair(blocks, multiplicities);
69  }
70 
71  std::string
72  component_name(const std::string &component_names,
73  const std::string &selected_component)
74  {
75  const auto components = Utilities::split_string_list(component_names);
76  std::string name = selected_component;
77  // Try normal and tangential components
78  {
79  const auto c = Utilities::split_string_list(selected_component, ".");
80  if (c.size() == 2)
81  {
82  if (c[1] == "n" || c[1] == "t" || c[1] == "N" || c[1] == "T")
83  name = c[0];
84  else
85  {
86  AssertThrow(false,
87  ExcMessage("You asked for " + selected_component +
88  ", but I don' know how to interpret " +
89  c[1]));
90  }
91  }
92  }
93  // Try direct name now
94  if (std::find(components.begin(), components.end(), name) !=
95  components.end())
96  {
97  return name;
98  }
99  // That didn't work. Se if we are asking for all components
100  if (selected_component == "all" || selected_component == "ALL")
101  {
102  // We return the first component
103  return components[0];
104  }
105  // Nothing else worked. Try numbers.
106  else
107  {
108  try
109  {
110  unsigned int c = Utilities::string_to_int(selected_component);
111  AssertThrow(c < components.size(),
112  ExcMessage(
113  "You asked for component " + selected_component +
114  ", but there are only " +
115  Utilities::int_to_string(components.size()) +
116  " components."));
117  return components[c];
118  }
119  catch (...)
120  {
121  // Nothing else worked. Throw an exception.
122  AssertThrow(false,
123  ExcMessage("You asked for " + selected_component +
124  ", but I don' know how to interpret it " +
125  "with names " + component_names));
126  }
127  }
128  return "";
129  }
130 
131 
132 
133  std::vector<unsigned int>
134  block_indices(const std::string &component_names,
135  const std::string &selected_components)
136  {
137  const auto &[b, m] = names_to_blocks(component_names);
138  const auto comps = Utilities::split_string_list(selected_components);
139  std::vector<unsigned int> indices;
140  for (const auto &c : comps)
141  {
142  const auto name = component_name(component_names, c);
143  const auto index = std::find(b.begin(), b.end(), name);
144  AssertThrow(index != b.end(),
145  ExcMessage("You asked for " + name +
146  ", but I don' know how to interpret it " +
147  "with names " + component_names));
148  indices.push_back(std::distance(b.begin(), index));
149  }
150  return indices;
151  }
152 
153 
154 
155  std::vector<unsigned int>
156  component_indices(const std::string &component_names,
157  const std::string &selected_components)
158  {
159  const auto &[b, m] = names_to_blocks(component_names);
160  const auto bi = block_indices(component_names, selected_components);
161  std::vector<unsigned int> indices;
162  for (const auto &i : bi)
163  indices.push_back(std::accumulate(m.begin(), m.begin() + i, 0));
164  return indices;
165  }
166 
167 
168 
169  std::pair<unsigned int, unsigned int>
170  component_to_indices(const std::string &component_names,
171  const std::string &selected_component)
172  {
173  const auto i1 = component_indices(component_names, selected_component);
174  const auto i2 = block_indices(component_names, selected_component);
175  AssertDimension(i1.size(), i2.size());
176  AssertThrow(i1.size() == 1,
177  ExcMessage("You asked for " + selected_component +
178  " components, but only one component at a time "
179  "should be passed to this function."));
180  return std::make_pair(i1[0], i2[0]);
181  }
182 
183 
184 
185  Type
186  type(const std::string &component_names,
187  const std::string &selected_component)
188  {
189  // Simple case: all components
190  if (selected_component == "all" || selected_component == "ALL")
191  return Type::all;
192 
193  const auto &[b, m] = names_to_blocks(component_names);
194  {
195  // Normal and tangential
196  const auto c = Utilities::split_string_list(selected_component, ".");
197  if (c.size() == 2)
198  {
199  if (c[1] == "n" || c[1] == "N")
200  return Type::normal;
201  else if (c[1] == "t" || c[1] == "T")
202  return Type::tangential;
203  }
204  }
205  // Now check if we have a scalar or a vector
206  const auto &[ci, bi] =
207  component_to_indices(component_names, selected_component);
208  if (m[bi] == 1)
209  return Type::scalar;
210  else
211  return Type::vector;
212  }
213 
214 
215 
216  unsigned int
217  n_blocks(const std::string &component_names)
218  {
219  const auto &[b, m] = names_to_blocks(component_names);
220  return b.size();
221  }
222 
223 
224 
226  mask(const std::string &component_names, const std::string &comp)
227  {
228  const unsigned int n = n_components(component_names);
229  std::vector<bool> _mask(n, false);
230  // Treat differently the case of numbers and the case of strings
231  try
232  {
233  const auto comps =
235  for (const auto &c : comps)
236  {
237  AssertThrow(c < n,
238  ExcMessage("You asked for component " +
240  ", but there are only " +
242  " components."));
243  _mask[c] = true;
244  }
245  return ComponentMask(_mask);
246  }
247  catch (...)
248  {
249  // First the "ALL" case.
250  if (comp == "ALL" || comp == "all")
251  {
252  for (unsigned int j = 0; j < n; ++j)
253  _mask[j] = true;
254  return ComponentMask(_mask);
255  }
256  // Then standard cases
257  const auto ids = component_indices(component_names, comp);
258  const auto bids = block_indices(component_names, comp);
259  const auto &[b, m] = names_to_blocks(component_names);
260  AssertDimension(ids.size(), bids.size());
261  for (unsigned int i = 0; i < ids.size(); ++i)
262  {
263  _mask[ids[i]] = true;
264  for (unsigned int j = 0; j < m[bids[i]]; ++j)
265  _mask[ids[i] + j] = true;
266  }
267  return ComponentMask(_mask);
268  }
269  }
270  } // namespace Components
271 } // namespace ParsedTools
#define AssertDimension(dim1, dim2)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::string to_string(const T &t)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
std::vector< std::string > split_string_list(const std::string &s, const std::string &delimiter=",")
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
int string_to_int(const std::string &s)
std::pair< unsigned int, unsigned int > component_to_indices(const std::string &component_names, const std::string &selected_component)
Return the indices within the components and within the blocks corresponding to first component of th...
Definition: components.cc:170
std::pair< std::vector< std::string >, std::vector< unsigned int > > names_to_blocks(const std::string &component_names)
Build block names and multiplicities from component names.
Definition: components.cc:56
std::string component_name(const std::string &component_names, const std::string &selected_component)
Return the canonical component name for the given selected component.
Definition: components.cc:72
Type
Enumerator used to identify patterns of components and their size in the a block system.
Definition: components.h:44
unsigned int n_blocks(const std::string &component_names)
Count the number of components in the given list of comma separated components.
Definition: components.cc:217
std::string blocks_to_names(const std::vector< std::string > &components, const std::vector< unsigned int > &multiplicities)
Build component names from block names and multiplicities.
Definition: components.cc:40
Type type(const std::string &component_name, const std::string &selected_component)
Return the component type for the given selected component.
Definition: components.cc:186
std::vector< unsigned int > block_indices(const std::string &component_names, const std::string &selected_components)
Return the indices within the block corresponding to the given selected components,...
Definition: components.cc:134
std::vector< unsigned int > component_indices(const std::string &component_names, const std::string &selected_components)
Return the indices within the components corresponding to first component of the given selected compo...
Definition: components.cc:156
ComponentMask mask(const std::string &component_names, const std::string &selected_component)
Return a component mask corresponding to a given selected component, from a list of comma separated c...
Definition: components.cc:226
unsigned int n_components(const std::string &component_names)
Count the number of components in the given list of comma separated components.
Definition: components.cc:32
We collect in this namespace some wrappers around commonly used deal.II classes, derived from the Par...