1 /*****************************************************************************
2 * *
3 * Elmer, A Finite Element Software for Multiphysical Problems *
4 * *
5 * Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License *
9 * as published by the Free Software Foundation; either version 2 *
10 * of the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program (in file fem/GPL-2); if not, write to the *
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, *
20 * Boston, MA 02110-1301, USA. *
21 * *
22 *****************************************************************************/
23
24 /*****************************************************************************
25 * *
26 * ElmerGUI sifgenerator *
27 * *
28 *****************************************************************************
29 * *
30 * Authors: Mikko Lyly, Juha Ruokolainen and Peter R�back *
31 * Email: Juha.Ruokolainen@csc.fi *
32 * Web: http://www.csc.fi/elmer *
33 * Address: CSC - IT Center for Science Ltd. *
34 * Keilaranta 14 *
35 * 02101 Espoo, Finland *
36 * *
37 * Original Date: 15 Mar 2008 *
38 * *
39 *****************************************************************************/
40
41 #include "sifgenerator.h"
42 #include <iostream>
43 #include <QDebug>
44
45 using namespace std;
46
SifGenerator()47 SifGenerator::SifGenerator()
48 {
49 }
50
~SifGenerator()51 SifGenerator::~SifGenerator()
52 {
53 }
54
setMesh(mesh_t * m)55 void SifGenerator::setMesh(mesh_t* m)
56 {
57 this->mesh = m;
58 }
59
setTextEdit(QTextEdit * textEdit)60 void SifGenerator::setTextEdit(QTextEdit* textEdit)
61 {
62 this->te = textEdit;
63 }
64
setDim(int n)65 void SifGenerator::setDim(int n)
66 {
67 this->dim = n;
68 }
69
setCdim(int n)70 void SifGenerator::setCdim(int n)
71 {
72 this->cdim = n;
73 }
74
setElmerDefs(QDomDocument * d)75 void SifGenerator::setElmerDefs(QDomDocument* d)
76 {
77 this->elmerDefs = d;
78 }
79
setGeneralSetup(GeneralSetup * g)80 void SifGenerator::setGeneralSetup(GeneralSetup* g)
81 {
82 this->generalSetup = g;
83 }
84
setEquationEditor(const QVector<DynamicEditor * > & d)85 void SifGenerator::setEquationEditor(const QVector<DynamicEditor*>& d)
86 {
87 this->equationEditor = d;
88 }
89
setMaterialEditor(const QVector<DynamicEditor * > & d)90 void SifGenerator::setMaterialEditor(const QVector<DynamicEditor*>& d)
91 {
92 this->materialEditor = d;
93 }
94
setBodyForceEditor(const QVector<DynamicEditor * > & d)95 void SifGenerator::setBodyForceEditor(const QVector<DynamicEditor*>& d)
96 {
97 this->bodyForceEditor = d;
98 }
99
setInitialConditionEditor(const QVector<DynamicEditor * > & d)100 void SifGenerator::setInitialConditionEditor(const QVector<DynamicEditor*>& d)
101 {
102 this->initialConditionEditor = d;
103 }
104
setBoundaryConditionEditor(const QVector<DynamicEditor * > & d)105 void SifGenerator::setBoundaryConditionEditor(const QVector<DynamicEditor*>& d)
106 {
107 this->boundaryConditionEditor = d;
108 }
109
setSolverParameterEditor(const QVector<SolverParameterEditor * > & s)110 void SifGenerator::setSolverParameterEditor(const QVector<SolverParameterEditor*>& s)
111 {
112 this->solverParameterEditor = s;
113 }
114
setBoundaryPropertyEditor(const QVector<BoundaryPropertyEditor * > & b)115 void SifGenerator::setBoundaryPropertyEditor(const QVector<BoundaryPropertyEditor*>& b)
116 {
117 this->boundaryPropertyEditor = b;
118 }
119
setBodyPropertyEditor(const QVector<BodyPropertyEditor * > & b)120 void SifGenerator::setBodyPropertyEditor(const QVector<BodyPropertyEditor*>& b)
121 {
122 this->bodyPropertyEditor = b;
123 }
124
setMeshControl(MeshControl * m)125 void SifGenerator::setMeshControl(MeshControl* m)
126 {
127 this->meshControl = m;
128 }
129
setLimit(Limit * l)130 void SifGenerator::setLimit(Limit* l)
131 {
132 this->limit = l;
133 }
134
135 // Make Header-block:
136 //-----------------------------------------------------------------------------
makeHeaderBlock()137 void SifGenerator::makeHeaderBlock()
138 {
139 Ui::setupDialog ui = generalSetup->ui;
140
141 te->append("Header");
142
143 if(ui.checkKeywordsWarn->isChecked())
144 te->append(" CHECK KEYWORDS Warn");
145
146 QString qs1 = ui.meshDBEdit1->text().trimmed();
147 QString qs2 = ui.meshDBEdit2->text().trimmed();
148 QString qs3 = ui.includePathEdit->text().trimmed();
149 QString qs4 = ui.resultsDirectoryEdit->text().trimmed();
150 QString qs5 = ui.headerFreeTextEdit->toPlainText();
151
152 te->append(" Mesh DB \"" + qs1 + "\" \"" + qs2 + "\"");
153 te->append(" Include Path \"" + qs3 + "\"");
154 te->append(" Results Directory \"" + qs4 + "\"");
155
156 if(!qs5.isEmpty())
157 te->append(qs5);
158
159 te->append("End\n");
160 }
161
162 // Make Simulation-block:
163 //-----------------------------------------------------------------------------
makeSimulationBlock()164 void SifGenerator::makeSimulationBlock()
165 {
166 Ui::setupDialog ui = generalSetup->ui;
167
168 te->append("Simulation");
169
170 addSifLine(" Max Output Level = ",
171 ui.maxOutputLevelCombo->currentText().trimmed());
172 addSifLine(" Coordinate System = ",
173 ui.coordinateSystemCombo->currentText().trimmed());
174 addSifLine(" Coordinate Mapping(3) = ",
175 ui.coordinateMappingEdit->text().trimmed());
176 addSifLine(" Simulation Type = ",
177 ui.simulationTypeCombo->currentText().trimmed());
178 addSifLine(" Steady State Max Iterations = ",
179 ui.steadyStateMaxIterEdit->text().trimmed());
180 addSifLine(" Output Intervals = ",
181 ui.outputIntervalsEdit->text().trimmed());
182 addSifLine(" Timestepping Method = ",
183 ui.timesteppingMethodCombo->currentText().trimmed());
184 addSifLine(" BDF Order = ",
185 ui.bdfOrderCombo->currentText().trimmed());
186 addSifLine(" Timestep intervals = ",
187 ui.timeStepIntervalsEdit->text().trimmed());
188 addSifLine(" Timestep Sizes = ",
189 ui.timestepSizesEdit->text().trimmed());
190
191 addSifLine(" Coordinate Scaling = ",
192 ui.coordinateScalingEdit->text().trimmed());
193 addSifLine(" Angular Frequency = ",
194 ui.angularFrequencyEdit->text().trimmed());
195
196 addSifLine(" Solver Input File = ",
197 ui.solverInputFileEdit->text().trimmed());
198 addSifLine(" Post File = ",
199 ui.postFileEdit->text().trimmed());
200
201 QString qs = ui.simulationFreeTextEdit->toPlainText();
202
203 if(!qs.isEmpty())
204 te->append(qs);
205
206 te->append("End\n");
207 }
208
209 // Make Constants-block:
210 //-----------------------------------------------------------------------------
makeConstantsBlock()211 void SifGenerator::makeConstantsBlock()
212 {
213 Ui::setupDialog ui = generalSetup->ui;
214
215 te->append("Constants");
216
217 addSifLine(" Gravity(4) = ",
218 ui.gravityEdit->text().trimmed());
219 addSifLine(" Stefan Boltzmann = ",
220 ui.stefanBoltzmannEdit->text().trimmed());
221 addSifLine(" Permittivity of Vacuum = ",
222 ui.vacuumPermittivityEdit->text().trimmed());
223 addSifLine(" Boltzmann Constant = ",
224 ui.boltzmannEdit->text().trimmed());
225 addSifLine(" Unit Charge = ",
226 ui.unitChargeEdit->text().trimmed());
227
228 QString qs = ui.constantsFreeTextEdit->toPlainText();
229
230 if(!qs.isEmpty())
231 te->append(qs);
232
233 te->append("End\n");
234 }
235
236
237 // Make Body-blocks:
238 //-----------------------------------------------------------------------------
makeBodyBlocks()239 void SifGenerator::makeBodyBlocks()
240 {
241 int i;
242
243 int sifIndex = 0, maxOriginalIndex=-1;
244
245 for(int index = 0; index < bodyMap.count(); index++) {
246
247 if(index >= bodyPropertyEditor.size()) {
248 cout << "SifGenerator: Body index out of bounds" << endl;
249 continue;
250 }
251
252 BodyPropertyEditor *bodyEdit = bodyPropertyEditor[index];
253
254 if(!bodyEdit)
255 continue;
256
257 int originalIndex = bodyMap.key(index);
258 maxOriginalIndex = max(maxOriginalIndex, originalIndex );
259
260 if(bodyEdit->touched) {
261 te->append("Body " + QString::number(++sifIndex));
262
263 te->append(" Target Bodies(1) = " + QString::number(originalIndex));
264
265 if ( bodyEdit->ui.nameEdit->text().trimmed() == "" )
266 te->append(" Name = \"Body " + QString::number(sifIndex) + "\"");
267 else
268 te->append(" Name = \"" + bodyEdit->ui.nameEdit->text().trimmed() + "\"");
269
270 i = bodyEdit->ui.equationCombo->currentIndex();
271 if(i > 0)
272 te->append(" Equation = " + QString::number(i));
273
274 i = bodyEdit->ui.materialCombo->currentIndex();
275 if(i > 0)
276 te->append(" Material = " + QString::number(i));
277
278 i = bodyEdit->ui.bodyForceCombo->currentIndex();
279 if(i > 0)
280 te->append(" Body Force = " + QString::number(i));
281
282 i = bodyEdit->ui.initialConditionCombo->currentIndex();
283 if(i > 0)
284 te->append(" Initial condition = " + QString::number(i));
285
286 te->append("End\n");
287 }
288 }
289
290 for( int index = 0; index < boundaryPropertyEditor.size(); index++ )
291 {
292 if(!boundaryPropertyEditor[index])
293 continue;
294
295 BodyPropertyEditor *bodyEdit = boundaryPropertyEditor[index]->bodyProperties;
296
297 if(!bodyEdit)
298 continue;
299
300 if(bodyEdit && bodyEdit->touched ) {
301 te->append("Body " + QString::number(++sifIndex));
302
303 boundaryPropertyEditor[index]->bodyID = ++maxOriginalIndex;
304
305 te->append(" Target Bodies(1) = " + QString::number(maxOriginalIndex));
306
307 if ( bodyEdit->ui.nameEdit->text().trimmed() == "" )
308 te->append(" Name = \"Body " + QString::number(sifIndex) + "\"");
309 else
310 te->append(" Name = \"" + bodyEdit->ui.nameEdit->text().trimmed() + "\"");
311
312 i = bodyEdit->ui.equationCombo->currentIndex();
313 if(i > 0)
314 te->append(" Equation = " + QString::number(i));
315
316 i = bodyEdit->ui.materialCombo->currentIndex();
317 if(i > 0)
318 te->append(" Material = " + QString::number(i));
319
320 i = bodyEdit->ui.bodyForceCombo->currentIndex();
321 if(i > 0)
322 te->append(" Body Force = " + QString::number(i));
323
324 i = bodyEdit->ui.initialConditionCombo->currentIndex();
325 if(i > 0)
326 te->append(" Initial condition = " + QString::number(i));
327
328 te->append("End\n");
329 }
330 }
331 }
332
333
findHashValue(DynamicEditor * de,const QString & sname,const QString & name)334 int SifGenerator::findHashValue(DynamicEditor *de, const QString &sname, const QString &name)
335 {
336 for(int i = 0; i < de->hash.count(); i++) {
337 hash_entry_t entry = de->hash.values().at(i);
338
339 QWidget *widget = entry.widget;
340 if (widget->isEnabled()) {
341 QString key = de->hash.keys().at(i);
342 QStringList keySplitted = key.split("/");
343 QString solverName = keySplitted.at(1).trimmed();
344 QString labelName = keySplitted.at(3).trimmed();
345
346 QDomElement elem = entry.elem;
347 if ( solverName==sname && labelName==name &&
348 elem.attribute("Widget","")=="Edit" ) {
349 QLineEdit *line = static_cast<QLineEdit*>(widget);
350 QString str = line->text().trimmed();
351 if ( str.isEmpty() ) return 0;
352 return str.toInt();
353 }
354 }
355 }
356 return 0;
357 }
358
359 // Make Equation/Solver -blocks:
360 //-----------------------------------------------------------------------------
makeEquationBlocks()361 void SifGenerator::makeEquationBlocks()
362 {
363 // Enumerate solvers && write solver blocks:
364 //-------------------------------------------
365 QMap<QString, int> numberForSolver;
366 numberForSolver.clear();
367
368 int solverNumber = 0;
369
370 for(int index = 0; index < equationEditor.size(); index++) {
371 DynamicEditor *eqEditor = equationEditor[index];
372
373 if(eqEditor->menuAction != NULL) {
374 for(int i = 0; i < eqEditor->hash.count(); i++) {
375 hash_entry_t entry = eqEditor->hash.values().at(i);
376
377 QWidget *widget = entry.widget;
378 if (widget->isEnabled()) {
379 QDomElement elem = entry.elem;
380
381 QString key = eqEditor->hash.keys().at(i);
382 QStringList keySplitted = key.split("/");
383 QString labelName = keySplitted.at(3).trimmed();
384 QString solverName = keySplitted.at(1).trimmed();
385
386 if(labelName=="Active" && elem.attribute("Widget", "")=="CheckBox") {
387 QCheckBox *checkBox = static_cast<QCheckBox*>(widget);
388 if(checkBox->isChecked()) {
389 if(!numberForSolver.contains(solverName)) {
390 int pri = findHashValue( eqEditor, solverName, "Priority");
391 numberForSolver.insert(solverName, pri);
392 }
393 }
394 }
395 }
396 }
397 }
398 }
399
400 // Sort and enumerate solvers according to their priority:
401 //---------------------------------------------------------
402 QList<QPair<int, QString> > tmpList;
403
404 foreach(const QString &key, numberForSolver.keys()) {
405 int value = numberForSolver.value(key);
406 tmpList << qMakePair(value, key);
407 }
408
409 qSort(tmpList);
410
411 numberForSolver.clear();
412
413 int n = tmpList.count();
414
415 for(int i = 0; i < n; i++) {
416 const QPair<int, QString> &pair = tmpList[i];
417 const QString &key = pair.second;
418 numberForSolver.insert(key, n-i);
419 }
420
421 // Generate solver blocks:
422 //-------------------------
423 QMap<int, int> handled;
424
425 for(int index = 0; index < equationEditor.size(); index++) {
426 DynamicEditor *eqEditor = equationEditor[index];
427 if(eqEditor->menuAction != NULL) {
428 for(int i = 0; i < eqEditor->hash.count(); i++) {
429 hash_entry_t entry = eqEditor->hash.values().at(i);
430
431 QWidget *widget = entry.widget;
432 if (widget->isEnabled()) {
433 QString key = eqEditor->hash.keys().at(i);
434 QStringList keySplitted = key.split("/");
435 QString solverName = keySplitted.at(1).trimmed();
436 QString labelName = keySplitted.at(3).trimmed();
437 QDomElement elem = entry.elem;
438
439 if(labelName=="Active" && elem.attribute("Widget", "")=="CheckBox") {
440 QCheckBox *checkBox = static_cast<QCheckBox*>(widget);
441 if(checkBox->isChecked()) {
442 solverNumber = numberForSolver.value(solverName);
443 if((solverNumber>0) && (handled[solverNumber]==0)) {
444 handled[solverNumber] = 1;
445 te->append("Solver " + QString::number(solverNumber));
446 te->append(" Equation = " + solverName);
447 makeSolverBlocks(solverName);
448 te->append("End");
449 te->append("");
450 }
451 }
452 }
453 }
454 }
455 }
456 }
457
458 // Generate equation blocks:
459 //---------------------------
460 QMap<int, bool> solverActive;
461
462 int sifIndex = 0;
463 for(int index = 0; index < equationEditor.size(); index++) {
464 DynamicEditor *eqEditor = equationEditor[index];
465
466 if(eqEditor->menuAction != NULL) {
467 te->append("Equation " + QString::number(++sifIndex));
468
469 QString name = eqEditor->nameEdit->text().trimmed();
470 te->append(" Name = \"" + name + "\"");
471
472 QString solverString = "";
473 int nofSolvers = 0;
474
475 for( int i=0; i < solverParameterEditor.size(); i++ )
476 solverActive[i] = false;
477
478 for(int i = 0; i < eqEditor->hash.count(); i++) {
479 hash_entry_t entry = eqEditor->hash.values().at(i);
480 QWidget *widget = entry.widget;
481
482 if(widget->isEnabled()) {
483 QDomElement elem = entry.elem;
484 QString key = eqEditor->hash.keys().at(i);
485 QStringList keySplitted = key.split("/");
486 QString solverName = keySplitted.at(1).trimmed();
487 QString labelName = keySplitted.at(3).trimmed();
488
489 // solver active?
490 if((labelName == "Active") && (elem.attribute("Widget", "") == "CheckBox")) {
491 QCheckBox *checkBox = static_cast<QCheckBox*>(widget);
492 if(checkBox->isChecked()) {
493 nofSolvers++;
494 solverNumber = numberForSolver.value(solverName);
495 solverActive[solverNumber] = true;
496 solverString += " " + QString::number(solverNumber);
497 }
498 }
499 }
500 }
501
502 for(int i = 0; i < eqEditor->hash.count(); i++) {
503 hash_entry_t entry = eqEditor->hash.values().at(i);
504 QWidget *widget = entry.widget;
505
506 if(widget->isEnabled()) {
507 QDomElement elem = entry.elem;
508 QString key = eqEditor->hash.keys().at(i);
509 QStringList keySplitted = key.split("/");
510 QString solverName = keySplitted.at(1).trimmed();
511 QString labelName = keySplitted.at(3).trimmed();
512
513 solverNumber = numberForSolver.value(solverName);
514 if ( !solverActive[solverNumber] ) continue;
515
516 if((elem.attribute("Widget", "") == "CheckBox") &&
517 (labelName != "Active"))
518 handleCheckBox(elem, widget);
519
520 if(elem.attribute("Widget", "") == "Edit" &&
521 labelName != "Priority")
522 handleLineEdit(elem, widget);
523
524 if(elem.attribute("Widget", "") == "Combo")
525 handleComboBox(elem, widget);
526
527 if(elem.attribute("Widget", "") == "TextEdit")
528 handleTextEdit(elem, widget);
529 }
530 }
531
532 if(nofSolvers > 0)
533 te->append(" Active Solvers("
534 + QString::number(nofSolvers)
535 + ") =" + solverString);
536
537 te->append("End\n");
538 }
539 }
540 }
541
542 //-------------------------------------------------------------------------
makeSolverBlocks(const QString & solverName)543 void SifGenerator::makeSolverBlocks(const QString &solverName)
544 {
545 SolverParameterEditor *spe, *tmp;
546 Ui::solverParameterEditor ui;
547
548 bool found = false;
549 int current=-1;
550
551 for(int i = 0; i < solverParameterEditor.size(); i++) {
552 spe = solverParameterEditor[i];
553
554 if(!spe)
555 continue;
556
557 QString currentName = spe->solverName.trimmed();
558 if(currentName == solverName) {
559 found = true;
560 current = i;
561 break;
562 }
563 }
564
565 if(!found) {
566 tmp = new SolverParameterEditor;
567 } else {
568 tmp = spe;
569 }
570
571 if ( !tmp->generalOptions ) {
572 tmp->generalOptions = new DynamicEditor;
573 tmp->generalOptions->setupTabs(elmerDefs, "Solver", current );
574 }
575
576 bool hasMatrix = parseSolverSpecificTab(tmp->generalOptions, solverName);
577
578 ui = tmp->ui;
579
580 // Parse the exec solver also for non-PDE solvers
581 parseExecSolverTab(ui);
582
583 if(hasMatrix) {
584 parseNumericalTechniquesTab(ui);
585 parseSteadyStateTab(ui);
586 parseNonlinearSystemTab(ui);
587 parseLinearSystemTab(ui);
588 parseParallelTab(ui);
589 // todo: add adaptivity & multigrid
590 }
591
592 if(!found)
593 {
594 delete tmp->generalOptions;
595 delete tmp;
596 }
597 }
598
599 // Make Material-blocks:
600 //-----------------------------------------------------------------------------
makeMaterialBlocks()601 void SifGenerator::makeMaterialBlocks()
602 {
603 int sifIndex = 0;
604
605 for(int index = 0; index < materialEditor.size(); index++) {
606 DynamicEditor *matEditor = materialEditor[index];
607
608 if(matEditor->menuAction != NULL) {
609 te->append("Material " + QString::number(++sifIndex));
610
611 QString name = matEditor->nameEdit->text().trimmed();
612 te->append(" Name = \"" + name + "\"");
613
614 for(int i = 0; i < matEditor->hash.count(); i++) {
615 hash_entry_t entry = matEditor->hash.values().at(i);
616
617 QWidget *widget = entry.widget;
618
619 QDomElement elem;
620 if ( widget->isEnabled() ) {
621 elem = entry.elem;
622
623 if(elem.attribute("Widget", "") == "CheckBox")
624 handleCheckBox(elem, widget);
625
626 if(elem.attribute("Widget", "") == "Edit")
627 handleLineEdit(elem, widget);
628
629 if(elem.attribute("Widget", "") == "Combo")
630 handleComboBox(elem, widget);
631
632 if(elem.attribute("Widget", "") == "TextEdit")
633 handleTextEdit(elem, widget);
634 }
635 }
636 te->append("End\n");
637 }
638 }
639 }
640
641
642 // Make body force blocks:
643 //-----------------------------------------------------------------------------
makeBodyForceBlocks()644 void SifGenerator::makeBodyForceBlocks()
645 {
646 int sifIndex = 0;
647
648 for(int index = 0; index < bodyForceEditor.size(); index++) {
649 DynamicEditor *bfEdit = bodyForceEditor[index];
650
651 if(bfEdit->menuAction != NULL) {
652 te->append("Body Force " + QString::number(++sifIndex));
653
654 QString name = bfEdit->nameEdit->text().trimmed();
655 te->append(" Name = \"" + name + "\"");
656
657 for(int i = 0; i < bfEdit->hash.count(); i++) {
658 hash_entry_t entry = bfEdit->hash.values().at(i);
659
660 QWidget *widget = entry.widget;
661
662 if ( widget->isEnabled() ) {
663 QDomElement elem = entry.elem;
664
665 if(elem.attribute("Widget", "") == "CheckBox")
666 handleCheckBox(elem, widget);
667
668 if(elem.attribute("Widget", "") == "Edit")
669 handleLineEdit(elem, widget);
670
671 if(elem.attribute("Widget", "") == "Combo")
672 handleComboBox(elem, widget);
673
674 if(elem.attribute("Widget", "") == "TextEdit")
675 handleTextEdit(elem, widget);
676 }
677 }
678 te->append("End\n");
679 }
680 }
681 }
682
683
684 // Make initial condition blocks:
685 //-----------------------------------------------------------------------------
makeInitialConditionBlocks()686 void SifGenerator::makeInitialConditionBlocks()
687 {
688 int sifIndex = 0;
689
690 for(int index = 0; index < initialConditionEditor.size(); index++) {
691 DynamicEditor *icEdit = initialConditionEditor[index];
692
693 if(icEdit->menuAction != NULL) {
694 te->append("Initial Condition " + QString::number(++sifIndex));
695
696 QString name = icEdit->nameEdit->text().trimmed();
697 te->append(" Name = \"" + name + "\"");
698
699 for(int i = 0; i < icEdit->hash.count(); i++) {
700 hash_entry_t entry = icEdit->hash.values().at(i);
701
702 QWidget *widget = entry.widget;
703
704 if ( widget->isEnabled() ) {
705 QDomElement elem = entry.elem;
706
707 if(elem.attribute("Widget", "") == "CheckBox")
708 handleCheckBox(elem, widget);
709
710 if(elem.attribute("Widget", "") == "Edit")
711 handleLineEdit(elem, widget);
712
713 if(elem.attribute("Widget", "") == "Combo")
714 handleComboBox(elem, widget);
715
716 if(elem.attribute("Widget", "") == "TextEdit")
717 handleTextEdit(elem, widget);
718 }
719 }
720 te->append("End\n");
721 }
722 }
723 }
724
725
726
727 // Make boundary blocks:
728 //-----------------------------------------------------------------------------
makeBoundaryBlocks()729 void SifGenerator::makeBoundaryBlocks()
730 {
731 int sifIndex = 0;
732 int bcnum = 0;
733 int diff = 0;
734 QMap<int, int> boundaryBC;
735 QMap<QString, int> boundaryList; /*(Boundary condition, edge) value pairs */
736 QList<QString> boundaryConditions; /* List of different boundary conditions */
737 QList<int> boundaryEdges; /* List of edges relating to some specific boundary condition */
738 QString tmp;
739
740 boundaryBC.clear();
741 boundaryList.clear();
742 boundaryConditions.clear();
743 boundaryEdges.clear();
744 tmp.clear();
745
746 //Find the available boundary conditions
747 for (int index = 0; index < boundaryConditionEditor.count(); index++) {
748 DynamicEditor *bc = boundaryConditionEditor[index];
749 boundaryConditions.append(bc->nameEdit->text().trimmed());
750 }
751
752 //Find the boundary conditions and edges related to them.
753 for (int index = 0; index < boundaryConditions.count(); index++) {
754 for(int k = 0; k < boundaryMap.count(); k++) {
755 BoundaryPropertyEditor *bEdit = boundaryPropertyEditor[k];
756 if(bEdit->touched) {
757 boundaryBC[index] = ++sifIndex;
758 int originalIndex = boundaryMap.key(k);
759 const QString bcname = bEdit->ui.boundaryConditionCombo->currentText().trimmed();
760 if (boundaryConditions.value(index) == bcname)
761 boundaryList.insertMulti(bcname, originalIndex);
762 }
763 }
764 }
765 //qDebug() << "boundaryMap: " << boundaryMap;
766 //qDebug() << "boundaryList: " << boundaryList;
767 qDebug() << "boundaryConditions: " << boundaryConditions;
768
769 //Arrange and sort boundary conditions
770 for(int index = 0; index < boundaryConditions.count(); index++) {
771 tmp.clear();
772 boundaryEdges.clear();
773 const QString name = boundaryConditions[index];
774 BoundaryPropertyEditor *bEdit = boundaryPropertyEditor[index];
775 DynamicEditor *bc = boundaryConditionEditor[index];
776
777 if(boundaryList.contains(name)) {
778 bcnum++;
779 te->append("Boundary Condition " + QString::number(bcnum));
780 if(boundaryConditions.count() > 1) {
781 QMap <QString,int>::ConstIterator l = boundaryList.find(boundaryConditions[index]);
782 while (l != boundaryList.end() && l.key()==boundaryConditions[index]){
783 boundaryEdges.append(l.value());
784 l++;
785 }
786 while ((l--) != boundaryList.begin() && l.key()==boundaryConditions[index]){
787 tmp.append(QString::number(l.value()));
788 tmp.append(" ");
789 }
790 }
791 if(boundaryConditions.count() <= 1) {
792 QMap <QString,int>::ConstIterator l = boundaryList.begin();
793 while (l != boundaryList.end()) {
794 boundaryEdges.append(l.value());
795 l++;
796 }
797 while ((l--) != boundaryList.begin()){
798 tmp.append(QString::number(l.value()));
799 tmp.append(" ");
800 }
801 }
802
803 te->append(" Target Boundaries("
804 + QString::number(boundaryEdges.count())
805 + ") = " + tmp);
806
807 if ( bEdit->bodyProperties ) {
808 te->append(" Body id = " + QString::number(bEdit->bodyID) );
809 }
810
811 te->append(" Name = \"" + name + "\"");
812
813 // check which one of the dynamic editors has "name" typed in nameEdit:
814 for(int j = 0; j < boundaryConditionEditor.size(); j++) {
815 DynamicEditor *bc = boundaryConditionEditor[j];
816 if(bc->menuAction != NULL) {
817 if(bc->nameEdit->text().trimmed() == name && name != NULL) {
818
819 // go through the hash of this dynamic editor:
820 //--------------------------------------------
821 for(int i = 0; i < bc->hash.count(); i++) {
822 hash_entry_t entry = bc->hash.values().at(i);
823
824 QWidget *widget = entry.widget;
825
826 QDomElement elem;
827 if ( widget->isEnabled() ) {
828 elem = entry.elem;
829
830 if(elem.attribute("Widget", "") == "CheckBox")
831 handleCheckBox(elem, widget);
832
833 if(elem.attribute("Widget", "") == "Edit")
834 handleBCLineEdit(elem, widget, boundaryBC);
835
836 if(elem.attribute("Widget", "") == "Combo")
837 handleComboBox(elem, widget);
838
839 if(elem.attribute("Widget", "") == "TextEdit")
840 handleTextEdit(elem, widget);
841 }
842 }
843 }
844 }
845 }
846 te->append("End\n");
847 }
848 }
849 }
850
851 // Parse "Solver specific tab"
852 //-----------------------------------------------------------------------------
parseSolverSpecificTab(DynamicEditor * solEditor,const QString & solverName)853 bool SifGenerator::parseSolverSpecificTab(DynamicEditor *solEditor, const QString &solverName)
854 {
855 // Returns true if there is a matrix involved. otherwise returns false.
856 if ( !solEditor ) return false;
857
858 bool hasMatrix = true;
859
860 QScriptEngine engine;
861
862 QScriptValue dim_QSV = QScriptValue(&engine,dim);
863 engine.globalObject().setProperty( "dim", dim_QSV );
864
865 QScriptValue cdim_QSV = QScriptValue(&engine,cdim);
866 engine.globalObject().setProperty( "cdim", cdim_QSV );
867
868 for(int i = 0; i < solEditor->hash.count(); i++) {
869 hash_entry_t entry = solEditor->hash.values().at(i);
870
871 QString key = solEditor->hash.keys().at(i);
872 QStringList keySplitted = key.split("/");
873 QString tabName = keySplitted.at(1).trimmed();
874 QString labelName = keySplitted.at(3).trimmed();
875
876 if ( tabName != solverName ) continue;
877
878 // Has matrix?
879 if(labelName == "No Matrix Equation") {
880 if(entry.elem.attribute("Widget", "") == "CheckBox") {
881 QCheckBox *cb = static_cast<QCheckBox*>(entry.widget);
882 hasMatrix = !cb->isChecked();
883 }
884 }
885
886 // variable names handled separately...
887 // ------------------------------------
888 if ( labelName=="Variable" || labelName.mid(0,17)=="Exported Variable" ) {
889 if( entry.elem.attribute("Widget", "") != "Edit") continue;
890
891 QLineEdit *l = static_cast<QLineEdit*>(entry.widget);
892 QString varName = l->text().trimmed();
893
894 if ( varName == "" ) continue;
895
896 int dofs=1;
897 QStringList dofsplit = varName.split("[");
898 if ( dofsplit.count()>1 ) {
899 varName = dofsplit.at(0).trimmed() + "[";
900 QString dof = dofsplit.at(1).trimmed();
901 dof = dof.split("]").at(0).trimmed();
902
903 dofsplit = dof.split(":");
904 QString subVarName = dofsplit.at(0).trimmed();
905 for( int i=1; i<dofsplit.count(); i++)
906 {
907 dof = dofsplit.at(i).trimmed();
908
909 QStringList subDofSplit = dof.split(" ");
910 QString subDof = subDofSplit.at(0).trimmed();
911
912 dofs = engine.evaluate(subDof).toInt32();
913 if (i>1) varName = varName + " ";
914 varName = varName + subVarName + ":" + QString::number(dofs);
915
916 if ( subDofSplit.count() > 1 )
917 subVarName = subDofSplit.at(1).trimmed();
918 }
919 varName = varName + "]";
920 addSifLine( " " + labelName + " = ", varName );
921 } else {
922 dofsplit = varName.split("(");
923 if ( dofsplit.count()>1 ) {
924 varName = dofsplit.at(0).trimmed();
925 QString dof = dofsplit.at(1).trimmed();
926 dofsplit = dof.split(")");
927 dof = dofsplit.at(0).trimmed();
928 dofs = engine.evaluate(dof).toInt32();
929 }
930 // Don't write the the trivial dof==1 case as this leaves possibility to define the number of
931 // dofs internally within the solver.
932 if ( dofs <= 1 ) {
933 addSifLine( " "+labelName+" = ", varName );
934 dofs = 1;
935 }
936 else {
937 addSifLine( " "+labelName+" = -dofs ", QString::number(dofs) + " " + varName );
938 }
939 }
940 continue;
941 }
942
943 QWidget *widget = entry.widget;
944
945 QDomElement elem;
946 if ( widget->isEnabled() ) {
947 elem = entry.elem;
948
949 if(elem.attribute("Widget", "") == "CheckBox")
950 handleCheckBox(elem, widget);
951
952 if(elem.attribute("Widget", "") == "Edit")
953 handleLineEdit(elem, widget);
954
955 if(elem.attribute("Widget", "") == "Combo")
956 handleComboBox(elem, widget);
957
958 if(elem.attribute("Widget", "") == "TextEdit")
959 handleTextEdit(elem, widget);
960 }
961 }
962
963 return hasMatrix;
964 }
965
966 // Parse "Exec Solver" tab from ui to sif:
967 //-----------------------------------------------------------------------------
parseExecSolverTab(Ui::solverParameterEditor ui)968 void SifGenerator::parseExecSolverTab(Ui::solverParameterEditor ui)
969 {
970 if(ui.execAlways->isChecked())
971 te->append(" Exec Solver = Always");
972
973 if(ui.execBeforeSimulation->isChecked())
974 te->append(" Exec Solver = Before Simulation");
975
976 if(ui.execAfterSimulation->isChecked())
977 te->append(" Exec Solver = After Simulation");
978
979 if(ui.execBeforeTimestep->isChecked())
980 te->append(" Exec Solver = Before Timestep");
981
982 if(ui.execAfterTimestep->isChecked())
983 te->append(" Exec Solver = After Timestep");
984
985 if(ui.execBeforeSaving->isChecked())
986 te->append(" Exec Solver = Before Saving");
987
988 if(ui.execAfterSaving->isChecked())
989 te->append(" Exec Solver = After Saving");
990
991 if(ui.execNever->isChecked())
992 te->append(" Exec Solver = Never");
993 }
994
995 // Parse "Numerical Techniques" tab from ui to sif:
996 //-----------------------------------------------------------------------------
parseNumericalTechniquesTab(Ui::solverParameterEditor ui)997 void SifGenerator::parseNumericalTechniquesTab(Ui::solverParameterEditor ui)
998 {
999 addSifLineBool(" Stabilize = ", ui.stabilizeCheck->isChecked());
1000 addSifLineBool(" Bubbles = ", ui.bubblesCheck->isChecked());
1001 addSifLineBool(" Lumped Mass Matrix = ", ui.lumpedMassCheck->isChecked());
1002 addSifLineBool(" Optimize Bandwidth = ", ui.optimizeBandwidthCheck->isChecked());
1003 }
1004
1005
1006 // Parse "Steady state" tab from ui to sif:
1007 //-----------------------------------------------------------------------------
parseSteadyStateTab(Ui::solverParameterEditor ui)1008 void SifGenerator::parseSteadyStateTab(Ui::solverParameterEditor ui)
1009 {
1010 if(ui.steadyStateConvergenceToleranceEdit->text() == "") {
1011 cout << "Steady state convergence tolerance is undefined - aborting" << endl;
1012 return;
1013 }
1014
1015 addSifLine(" Steady State Convergence Tolerance = ",
1016 ui.steadyStateConvergenceToleranceEdit->text());
1017
1018 if( ui.steadyStateConvergenceMeasureCombo->currentText().trimmed() != "Norm")
1019 addSifLine(" Steady State Convergence Measure = ",
1020 ui.steadyStateConvergenceMeasureCombo->currentText().trimmed());
1021 }
1022
1023
1024 // Parse "Nonlinear system" tab from ui to sif:
1025 //-----------------------------------------------------------------------------
parseNonlinearSystemTab(Ui::solverParameterEditor ui)1026 void SifGenerator::parseNonlinearSystemTab(Ui::solverParameterEditor ui)
1027 {
1028 addSifLine(" Nonlinear System Convergence Tolerance = ",
1029 ui.nonlinSystemConvergenceToleranceEdit->text());
1030
1031 addSifLine(" Nonlinear System Max Iterations = ",
1032 ui.nonlinSystemMaxIterationEdit->text());
1033
1034 addSifLine(" Nonlinear System Newton After Iterations = ",
1035 ui.nonlinSystemNewtonAfterIterEdit->text());
1036
1037 addSifLine(" Nonlinear System Newton After Tolerance = ",
1038 ui.nonlinSystemNewtonAfterTolEdit->text());
1039
1040 addSifLine(" Nonlinear System Relaxation Factor = ",
1041 ui.nonlinSystemRelaxationFactorEdit->text());
1042
1043 if( ui.nonlinSystemConvergenceMeasureCombo->currentText().trimmed() != "Norm")
1044 addSifLine(" Nonlinear System Convergence Measure = ",
1045 ui.nonlinSystemConvergenceMeasureCombo->currentText().trimmed());
1046
1047 }
1048
1049
1050 // Parse "Parallel" tab from ui to sif:
1051 //-----------------------------------------------------------------------------
parseParallelTab(Ui::solverParameterEditor ui)1052 void SifGenerator::parseParallelTab(Ui::solverParameterEditor ui)
1053 {
1054 if(ui.useHypre->isChecked()) {
1055 addSifLine(" Linear System Use HYPRE = ", "True");
1056
1057 if(ui.useParasails->isChecked()) {
1058 addSifLine(" Linear System Preconditioning = ", "ParaSails");
1059
1060 addSifLine(" ParaSails Threshold = ",
1061 ui.thresholdEdit->text().trimmed());
1062
1063 addSifLine(" ParaSails Filter = ",
1064 ui.filterEdit->text().trimmed());
1065
1066 addSifLine(" ParaSails MaxLevel = ",
1067 ui.maxLevelEdit->text().trimmed());
1068
1069 addSifLine(" ParaSails Symmetry = ",
1070 ui.symmetryEdit->text().trimmed());
1071 }
1072
1073 if(ui.useBoomerAMG->isChecked()) {
1074 addSifLine(" Linear System Preconditioning = ", "BoomerAMG");
1075
1076 addSifLine(" BoomerAMG Relax Type = ",
1077 QString::number(ui.boomerRelaxation->currentIndex()));
1078
1079 addSifLine(" BoomerAMG Coarsen Type = ",
1080 QString::number(ui.boomerCoarsening->currentIndex()));
1081
1082 addSifLine(" BoomerAMG Num Sweeps = ",
1083 ui.boomerSweeps->text().trimmed());
1084
1085 addSifLine(" BoomerAMG Max Levels = ",
1086 ui.boomerMaxLevels->text().trimmed());
1087
1088 addSifLine(" BoomerAMG Interpolation = ",
1089 QString::number(ui.boomerInterpolation->currentIndex()));
1090
1091 addSifLine(" BoomerAMG Smooth Type = ",
1092 QString::number(ui.boomerSmoother->currentIndex()));
1093
1094 addSifLine(" BoomerAMG Cycle Type = ",
1095 QString::number(ui.boomerCycle->currentIndex()));
1096
1097 }
1098 }
1099 }
1100
1101
1102 // Parse "Linear system" tab from ui to sif:
1103 //-----------------------------------------------------------------------------
parseLinearSystemTab(Ui::solverParameterEditor ui)1104 void SifGenerator::parseLinearSystemTab(Ui::solverParameterEditor ui)
1105 {
1106 bool hyprePreconditioning
1107 = ui.useParasails->isChecked() | ui.useBoomerAMG->isChecked();
1108
1109 if(ui.linearSystemSolverDirect->isChecked()) {
1110
1111 addSifLine(" Linear System Solver = ", "Direct");
1112
1113 addSifLine(" Linear System Direct Method = ",
1114 ui.linearSystemDirectMethod->currentText());
1115
1116 } else if(ui.linearSystemSolverIterative->isChecked()) {
1117
1118 addSifLine(" Linear System Solver = ", "Iterative");
1119
1120 addSifLine(" Linear System Iterative Method = ",
1121 ui.linearSystemIterativeMethod->currentText());
1122
1123 addSifLine(" Linear System Max Iterations = ",
1124 ui.linearSystemMaxIterationsEdit->text());
1125
1126 addSifLine(" Linear System Convergence Tolerance = ",
1127 ui.linearSystemConvergenceToleranceEdit->text());
1128
1129 addSifLine(" BiCGstabl polynomial degree = ",
1130 ui.linearSystemBiCGstablPolDeg->text());
1131
1132 if(!hyprePreconditioning)
1133 addSifLine(" Linear System Preconditioning = ",
1134 ui.linearSystemPreconditioning->currentText());
1135
1136 addSifLine(" Linear System ILUT Tolerance = ",
1137 ui.linearSystemILUTToleranceEdit->text());
1138
1139 addSifLineBool(" Linear System Abort Not Converged = ",
1140 ui.linearSystemAbortWhenNotConvergedCheck->isChecked());
1141
1142 addSifLine(" Linear System Residual Output = ",
1143 ui.linearSystemResiduaOutputEdit->text());
1144
1145 addSifLine(" Linear System Precondition Recompute = ",
1146 ui.linearSystemPreconditionRecomputeEdit->text());
1147
1148 } else if(ui.linearSystemSolverMultigrid->isChecked()) {
1149
1150 addSifLine(" Linear System Solver = ", "Multigrid");
1151
1152 // TODO: rest of the less common params etc.
1153 }
1154 }
1155
1156 //------------------------------------------------------------------------
1157 //
1158 // COMMON UTILITY FUNCTIONS
1159 //
1160 //------------------------------------------------------------------------
1161
addSifLine(const QString & var,const QString & val)1162 void SifGenerator::addSifLine(const QString &var, const QString &val)
1163 {
1164 if(val != "")
1165 te->append(var + val);
1166 }
1167
addSifLineBool(const QString & var,bool val)1168 void SifGenerator::addSifLineBool(const QString &var, bool val)
1169 {
1170 if(val == true)
1171 te->append(var + "True");
1172 else
1173 te->append(var + "False");
1174 }
1175
1176
handleBCLineEdit(const QDomElement & elem,QWidget * widget,const QMap<int,int> & boundaryBC)1177 void SifGenerator::handleBCLineEdit(const QDomElement &elem, QWidget *widget, const QMap<int, int> &boundaryBC)
1178 {
1179 QString name = elem.firstChildElement("SifName").text().trimmed();
1180 if( name == "" )
1181 name= elem.firstChildElement("Name").text().trimmed();
1182
1183 QLineEdit *lineEdit = static_cast<QLineEdit*>(widget);
1184 QString value = lineEdit->text().trimmed();
1185
1186 if ( name=="Periodic BC" && value != "" )
1187 {
1188 int val = value.toInt();
1189 val = boundaryMap.value(val);
1190 value=QString::number(boundaryBC[val]);
1191 }
1192
1193 addSifLine(" " + name + " = ", value);
1194 }
1195
handleLineEdit(const QDomElement & elem,QWidget * widget)1196 void SifGenerator::handleLineEdit(const QDomElement &elem, QWidget *widget)
1197 {
1198 QString name = elem.firstChildElement("SifName").text().trimmed();
1199 if( name == "" )
1200 name= elem.firstChildElement("Name").text().trimmed();
1201
1202 QLineEdit *lineEdit = static_cast<QLineEdit*>(widget);
1203 QString value = lineEdit->text().trimmed();
1204 addSifLine(" " + name + " = ", value);
1205 }
1206
handleTextEdit(const QDomElement & elem,QWidget * widget)1207 void SifGenerator::handleTextEdit(const QDomElement &elem, QWidget *widget)
1208 {
1209 QTextEdit *textEdit = static_cast<QTextEdit*>(widget);
1210 QString value = textEdit->toPlainText();
1211 if(!value.isEmpty()) te->append(value);
1212 }
1213
handleComboBox(const QDomElement & elem,QWidget * widget)1214 void SifGenerator::handleComboBox(const QDomElement &elem, QWidget *widget)
1215 {
1216 QString name = elem.firstChildElement("SifName").text().trimmed();
1217 if( name == "" )
1218 name= elem.firstChildElement("Name").text().trimmed();
1219
1220 QComboBox *comboBox = static_cast<QComboBox*>(widget);
1221 QString value = comboBox->currentText().trimmed();
1222
1223 if(value != "None")
1224 addSifLine(" " + name + " = ", value);
1225 }
1226
handleCheckBox(const QDomElement & elem,QWidget * widget)1227 void SifGenerator::handleCheckBox(const QDomElement &elem, QWidget *widget)
1228 {
1229 QString name = elem.firstChildElement("SifName").text().trimmed();
1230 if( name == "" )
1231 name = elem.firstChildElement("Name").text().trimmed();
1232
1233 QString def_val = elem.firstChildElement("DefaultValue").text().trimmed();
1234 if ( def_val == "" )
1235 def_val = "False";
1236
1237 QCheckBox *checkBox = static_cast<QCheckBox*>(widget);
1238
1239 if(checkBox->isChecked()) {
1240 if ( def_val != "True" )
1241 te->append(" " + name + " = True");
1242 } else {
1243 if ( def_val != "False" )
1244 te->append(" " + name + " = False");
1245 }
1246 }
1247