10void PrintErrorReadingFile(
const std::string& hdr,
const std::string& file,
12 std::cerr << hdr <<
"\n Error reading file " << file <<
" (line " << line
30 const std::string& elist,
31 const std::string& nlist,
32 const std::string& mplist,
33 const std::string& volt,
34 const std::string& unit)
37 Initialise(header, elist, nlist, mplist, volt, unit);
41 const std::string& elist,
42 const std::string& nlist,
43 const std::string& mplist,
44 const std::string& volt,
45 const std::string& unit) {
46 const std::string hdr =
m_className +
"::Initialise:";
53 constexpr int size = 100;
57 std::ifstream fheader(header);
64 fheader.getline(line, size,
'\n');
65 char* token = strtok(line,
" ");
66 bool readerror =
false;
67 const int nNodes =
ReadInteger(token, 0, readerror);
68 token = strtok(
nullptr,
" ");
69 const int nElements =
ReadInteger(token, 0, readerror);
70 std::cout << hdr <<
"\n Read " << nNodes <<
" nodes and " << nElements
71 <<
" elements from file " << header <<
".\n";
73 PrintErrorReadingFile(hdr, header, 0);
82 std::ifstream fnodes(nlist);
91 std::cerr << hdr <<
" Unknown length unit " << unit <<
" Will use cm.\n";
94 if (
m_debug) std::cout <<
" Unit scaling factor = " << funit <<
".\n";
97 for (
int il = 0; il < nNodes; il++) {
99 fnodes.getline(line, size,
'\n');
102 token = strtok(line,
" ");
103 token = strtok(
nullptr,
" ");
106 token = strtok(
nullptr,
" ");
107 double xnode =
ReadDouble(token, -1, readerror);
108 token = strtok(
nullptr,
" ");
109 double ynode =
ReadDouble(token, -1, readerror);
110 token = strtok(
nullptr,
" ");
111 double znode =
ReadDouble(token, -1, readerror);
113 PrintErrorReadingFile(hdr, nlist, il);
120 node.
x = xnode * funit;
121 node.
y = ynode * funit;
122 node.
z = znode * funit;
123 m_nodes.push_back(std::move(node));
130 if (!LoadPotentials(volt,
m_pot))
return false;
133 std::ifstream fmplist(mplist);
140 fmplist.getline(line, size,
'\n');
141 token = strtok(line,
" ");
143 std::cerr << hdr <<
"\n Error reading number of materials from "
148 const unsigned int nMaterials =
ReadInteger(token, 0, readerror);
153 material.medium =
nullptr;
155 for (
int il = 2; il < ((int)nMaterials + 2); il++) {
156 fmplist.getline(line, size,
'\n');
157 token = strtok(line,
" ");
159 token = strtok(
nullptr,
" ");
160 double dc =
ReadDouble(token, -1.0, readerror);
162 PrintErrorReadingFile(hdr, mplist, il);
167 std::cout <<
" Set material " << il - 2 <<
" of "
168 << nMaterials <<
" to eps " << dc <<
".\n";
178 std::ifstream felems(elist);
185 for (
int il = 0; il < nElements; il++) {
187 felems.getline(line, size,
'\n');
190 token = strtok(line,
" ");
192 token = strtok(
nullptr,
" ");
194 token = strtok(
nullptr,
" ");
195 std::vector<int> inode;
196 for (
size_t k = 0; k < 8; ++k) {
197 token = strtok(
nullptr,
" ");
199 if (!readerror) inode.push_back(in);
201 token = strtok(
nullptr,
" ");
202 if (inode.size() != 8) {
203 PrintErrorReadingFile(hdr, elist, il);
204 std::cerr <<
" Read " << inode.size() <<
" node indices for element"
205 << il <<
" (expected 8).\n";
211 std::cout <<
" Read nodes ";
212 for (
size_t k = 0; k < 8; ++k) {
213 std::cout << inode[k];
214 if (k < 7) std::cout <<
", ";
216 std::cout <<
"\n from element " << il + 1 <<
" of "
217 << nElements <<
" with material " << imat <<
".\n";
221 if (imat < 0 || imat > (
int)nMaterials) {
222 std::cerr << hdr <<
"\n Out-of-range material number on file " << elist
223 <<
" (line " << il <<
").\n";
224 std::cerr <<
" Element: " << il <<
", material: " << imat <<
"\n";
229 std::cerr << hdr <<
"\n Element " << il <<
" in " << elist <<
"\n"
230 <<
" uses material " << imat <<
" which does not have\n"
231 <<
" a positive permittivity in " << mplist <<
".\n";
237 bool degenerate =
false;
238 for (
size_t k = 0; k < 8; ++k) {
240 std::cerr << hdr <<
"\n Found a node number < 1 on file " << elist
241 <<
" (line " << il <<
").\n Element: " << il
242 <<
", material: " << imat <<
".\n";
246 for (
size_t kk = k + 1; kk < 8; ++kk) {
247 if (inode[k] == inode[kk]) degenerate =
true;
251 std::cerr << hdr <<
"\n Element " << il <<
" of file " << elist
252 <<
" is degenerate,\n"
253 <<
" no such elements are allowed in this type of map.\n";
278 const double crossprod = x01 * y12 - y01 * x12;
280 element.
emap[3] = inode[0] - 1;
281 element.
emap[2] = inode[1] - 1;
282 element.
emap[1] = inode[2] - 1;
283 element.
emap[0] = inode[3] - 1;
284 element.
emap[6] = inode[4] - 1;
285 element.
emap[5] = inode[5] - 1;
286 element.
emap[4] = inode[6] - 1;
287 element.
emap[7] = inode[7] - 1;
289 element.
emap[0] = inode[0] - 1;
290 element.
emap[1] = inode[1] - 1;
291 element.
emap[2] = inode[2] - 1;
292 element.
emap[3] = inode[3] - 1;
293 element.
emap[4] = inode[4] - 1;
294 element.
emap[5] = inode[5] - 1;
295 element.
emap[6] = inode[6] - 1;
296 element.
emap[7] = inode[7] - 1;
303 if (!ok)
return false;
308 std::cout <<
" Finished.\n";
315 const std::string& label) {
316 const std::string hdr =
m_className +
"::SetWeightingField:";
319 std::cerr <<
" Weighting field cannot be added.\n";
322 std::cout <<
m_className <<
"::SetWeightingField:\n"
323 <<
" Loading field map for electrode " << label <<
".\n";
325 if (
m_wpot.count(label) > 0) {
326 std::cout <<
" Replacing existing weighting field.\n";
329 std::vector<double> pot(
m_nodes.size(), 0.);
330 if (!LoadPotentials(wvolt, pot))
return false;
331 m_wpot[label] = std::move(pot);
335bool ComponentElmer2d::LoadPotentials(
const std::string& volt,
336 std::vector<double>& pot) {
339 std::ifstream fvolt(volt);
346 constexpr int size = 100;
351 bool readstop =
false;
352 while (!readstop && fvolt.getline(line, size,
'\n')) {
353 char* token = strtok(line,
" ");
354 if (token && strcmp(token,
"Perm:") == 0) readstop =
true;
361 <<
" Error reading past header of potentials file "
368 const auto nNodes =
m_nodes.size();
369 for (
size_t j = 0; j < nNodes; ++j) {
370 fvolt.getline(line, size,
'\n');
374 pot.assign(nNodes, 0.);
376 for (
size_t j = 0; j < nNodes; ++j) {
377 fvolt.getline(line, size,
'\n');
378 char* token = strtok(line,
" ");
379 bool readerror =
false;
382 PrintErrorReadingFile(
m_className +
"::LoadPotentials", volt, il);
392 std::cout <<
" Read potentials from file " << volt <<
".\n";
397 if (fabs(zmax - zmin) <= 0.) {
398 std::cerr <<
m_className <<
"::SetRangeZ: Zero range is not permitted.\n";
ComponentElmer2d()
Default constructor.
void SetRangeZ(const double zmin, const double zmax)
bool Initialise(const std::string &header="mesh.header", const std::string &elist="mesh.elements", const std::string &nlist="mesh.nodes", const std::string &mplist="dielectrics.dat", const std::string &volt="out.result", const std::string &unit="cm")
bool SetWeightingField(const std::string &prnsol, const std::string &label)
bool SetDefaultDriftMedium()
Find lowest epsilon, check for eps = 0, set default drift media flags.
static double ReadDouble(char *token, double def, bool &error)
std::array< double, 3 > m_maxBoundingBox
std::array< double, 3 > m_mapmin
std::vector< double > m_pot
std::array< double, 3 > m_minBoundingBox
static double ScalingFactor(std::string unit)
static int ReadInteger(char *token, int def, bool &error)
std::vector< Material > m_materials
ComponentFieldMap()=delete
Default constructor.
std::vector< Node > m_nodes
void PrintCouldNotOpen(const std::string &header, const std::string &filename) const
std::map< std::string, std::vector< double > > m_wpot
std::vector< Element > m_elements
std::vector< bool > m_degenerate
ElementType m_elementType
std::array< double, 3 > m_mapmax
void Reset() override
Reset the component.
void PrintNotReady(const std::string &header) const
bool m_debug
Switch on/off debugging messages.
std::string m_className
Class name.
bool m_ready
Ready for use?