/*************************************************************************** * Copyright (c) 2013 Jan Rheinländer * * Copyright (c) 2016 Qingfeng Xia * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ # include # include # include # include # include # include # include # include # include # include # include # include # include #endif #include "ui_TaskFemConstraintFluidBoundary.h" #include "TaskFemConstraintFluidBoundary.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ActiveAnalysisObserver.h" #include #include using namespace FemGui; using namespace Gui; using namespace Fem; //also defined in FemConstrainFluidBoundary and foamcasebuilder/basicbuilder.py, please update simultaneously //the second (index 1) is the default enum, as index 0 causes compiling error //static const char* BoundaryTypes[] = {"inlet","wall","outlet","freestream", "interface", NULL}; static const char* WallSubtypes[] = {"unspecific", "fixed", "slip", "partialSlip", "moving", "rough", NULL}; static const char* InletSubtypes[] = {"unspecific","totalPressure","uniformVelocity","volumetricFlowRate","massFlowRate",NULL}; static const char* OutletSubtypes[] = {"unspecific","totalPressure","staticPressure","uniformVelocity", "outFlow", NULL}; static const char* InterfaceSubtypes[] = {"unspecific","symmetryPlane","wedge","cyclic","empty", "coupled", NULL}; static const char* FreestreamSubtypes[] = {"unspecific", "freestream",NULL}; static const char* InterfaceSubtypeHelpTexts[] = { "invalid,select other valid interface subtype", "symmetry plane but not axis-sym axis line", "axis symmetric front and back surfaces", "periodic boundary in pair, treated as physical connected", "front and back for single layer 2D mesh, also axis-sym axis line", "exchange boundary vale with external program, need extra manual setup like file name", NULL}; // defined in file FemConstraintFluidBoundary: // see Ansys fluet manual: Turbulence Specification method //static const char* TurbulenceSpecifications[] = {"intensity&DissipationRate", "intensity&LengthScale","intensity&ViscosityRatio", "intensity&HydraulicDiameter",NULL}; //activate the heat transfer and radiation model in Solver object explorer static const char* TurbulenceSpecificationHelpTexts[] = { "explicitly specific intensity k [SI unit] and dissipation rate epsilon [] / omega []", "intensity (0.05 ~ 0.15) and characteristic length scale of max eddy [m]", "intensity (0.05 ~ 0.15) and turbulent viscosity ratio", "for fully devloped internal flow, Turbulence intensity (0-1.0) 0.05 typical", NULL}; //static const char* ThermalBoundaryTypes[] = {"fixedValue","zeroGradient", "fixedGradient", "mixed", "heatFlux", "HTC","coupled", NULL}; //const char* ThermalBoundaryTypes[] = {"fixedValue","zeroGradient", "fixedGradient", "mixed", "coupled",NULL}; static const char* ThermalBoundaryHelpTexts[] = {"fixed Temperature [K]", "no heat transfer on boundary()", "fixed value gradient [W/m]", "mixed fixedGradient and fixedValue", "fixed heat flux [W/m2]", "Heat transfer coeff [W/(M2)/K]", "conjugate heat transfer with solid", NULL}; // enable & disable quantityUI once valueType is selected // internal function not declared in header file void initComboBox(QComboBox* combo, const std::vector& textItems, const char* sItem) { combo->blockSignals(true); int iItem = 1; // the first one is "unspecific" (index 0) combo->clear(); for (unsigned int it = 0; it < textItems.size(); it++) { combo->insertItem(it, Base::Tools::fromStdString(textItems[it])); if (sItem == textItems[it]) { iItem = it; } } combo->blockSignals(false); combo->setCurrentIndex(iItem); } /* TRANSLATOR FemGui::TaskFemConstraintFluidBoundary */ TaskFemConstraintFluidBoundary::TaskFemConstraintFluidBoundary(ViewProviderFemConstraintFluidBoundary *ConstraintView,QWidget *parent) : TaskFemConstraint(ConstraintView, parent, "fem-constraint-fluid-boundary") { // we need a separate container widget to add all controls to proxy = new QWidget(this); ui = new Ui_TaskFemConstraintFluidBoundary(); ui->setupUi(proxy); QMetaObject::connectSlotsByName(this); // Create a context menu for the listview of the references QAction* action = new QAction(tr("Delete"), ui->listReferences); action->connect(action, SIGNAL(triggered()), this, SLOT(onReferenceDeleted())); ui->listReferences->addAction(action); ui->listReferences->setContextMenuPolicy(Qt::ActionsContextMenu); connect(ui->comboBoundaryType, SIGNAL(currentIndexChanged(int)), this, SLOT(onBoundaryTypeChanged(void))); connect(ui->comboSubtype, SIGNAL(currentIndexChanged(int)), this, SLOT(onSubtypeChanged(void))); connect(ui->spinBoundaryValue, SIGNAL(valueChanged(double)), this, SLOT(onBoundaryValueChanged(double))); connect(ui->comboTurbulenceSpecification, SIGNAL(currentIndexChanged(int)), this, SLOT(onTurbulenceSpecificationChanged(void))); connect(ui->comboThermalBoundaryType, SIGNAL(currentIndexChanged(int)), this, SLOT(onThermalBoundaryTypeChanged(void))); connect(ui->buttonReference, SIGNAL(pressed()), this, SLOT(onButtonReference())); connect(ui->buttonDirection, SIGNAL(pressed()), this, SLOT(onButtonDirection())); connect(ui->checkReverse, SIGNAL(toggled(bool)), this, SLOT(onCheckReverse(bool))); this->groupLayout()->addWidget(proxy); // Temporarily prevent unnecessary feature recomputes ui->spinBoundaryValue->blockSignals(true); ui->listReferences->blockSignals(true); ui->buttonReference->blockSignals(true); ui->buttonDirection->blockSignals(true); ui->checkReverse->blockSignals(true); // Get the feature data Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); Fem::FemSolverObject* pcSolver = NULL; if (FemGui::ActiveAnalysisObserver::instance()->hasActiveObject()) { Fem::FemAnalysis* pcAnalysis = FemGui::ActiveAnalysisObserver::instance()->getActiveObject(); //Fem::FemSolverObject is derived from DocumentObject std::vector fem = pcAnalysis->Member.getValues(); for (std::vector::iterator it = fem.begin(); it != fem.end(); ++it) { if ((*it)->getTypeId().isDerivedFrom(Fem::FemSolverObject::getClassTypeId())) pcSolver = static_cast(*it); } } pHeatTransfering = NULL; pTurbulenceModel = NULL; if (pcSolver != NULL) { //if only it is CFD solver, otherwise exit by SIGSEGV error, detect getPropertyByName() != NULL if (pcSolver->getPropertyByName("HeatTransfering")) { pHeatTransfering = static_cast(pcSolver->getPropertyByName("HeatTransfering")); if (pHeatTransfering->getValue()) { ui->tabThermalBoundary->setEnabled(true); initComboBox(ui->comboThermalBoundaryType, pcConstraint->ThermalBoundaryType.getEnumVector(), pcConstraint->ThermalBoundaryType.getValueAsString()); updateThermalBoundaryUI(); } else { ui->tabThermalBoundary->setEnabled(false); //Base::Console().Message("retrieve solver property HeatTransfering as false\n"); } } else { ui->tabThermalBoundary->setEnabled(false); } if (pcSolver->getPropertyByName("TurbulenceModel")) { pTurbulenceModel = static_cast(pcSolver->getPropertyByName("TurbulenceModel")); if (pTurbulenceModel->getValueAsString() == std::string("laminar")){ ui->tabTurbulenceBoundary->setEnabled(false); } else { ui->tabTurbulenceBoundary->setEnabled(true); ui->labelTurbulenceSpecification->setText(Base::Tools::fromStdString( pTurbulenceModel->getValueAsString())); initComboBox(ui->comboTurbulenceSpecification, pcConstraint->TurbulenceSpecification.getEnumVector(), pcConstraint->TurbulenceSpecification.getValueAsString()); updateTurbulenceUI(); } } else { ui->tabTurbulenceBoundary->setEnabled(false); } } else { Base::Console().Message("Warning: No solver object inside FemAnalysis object\n"); } ui->tabWidget->setTabText(0, tr("Basic")); ui->tabWidget->setTabText(1, tr("Turbulence")); ui->tabWidget->setTabText(2, tr("Thermal")); ui->tabWidget->setCurrentIndex(0); ui->labelHelpText->setText(tr("select boundary type, faces and set value")); initComboBox(ui->comboBoundaryType, pcConstraint->BoundaryType.getEnumVector(), pcConstraint->BoundaryType.getValueAsString()); updateBoundaryTypeUI(); //updateSubtypeUI(); // already called inside updateBoundaryTypeUI(); std::vector Objects = pcConstraint->References.getValues(); std::vector SubElements = pcConstraint->References.getSubValues(); std::vector dirStrings = pcConstraint->Direction.getSubValues(); QString dir; if (!dirStrings.empty()) dir = makeRefText(pcConstraint->Direction.getValue(), dirStrings.front()); // Fill data into dialog elements double f = pcConstraint->BoundaryValue.getValue(); ui->spinBoundaryValue->setMinimum(0); ui->spinBoundaryValue->setMaximum(FLOAT_MAX); ui->spinBoundaryValue->setValue(f); ui->listReferences->clear(); for (std::size_t i = 0; i < Objects.size(); i++) ui->listReferences->addItem(makeRefText(Objects[i], SubElements[i])); if (Objects.size() > 0) ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); ui->lineDirection->setText(dir.isEmpty() ? tr("") : dir); ui->checkReverse->setVisible(false); // no need such UI for fluid boundary, set by cpp code only ui->listReferences->blockSignals(false); ui->buttonReference->blockSignals(false); ui->spinBoundaryValue->blockSignals(false); ui->buttonDirection->blockSignals(false); ui->checkReverse->blockSignals(false); updateSelectionUI(); } void TaskFemConstraintFluidBoundary::updateBoundaryTypeUI() { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); std::string boundaryType = pcConstraint->BoundaryType.getValueAsString(); // Update subtypes, any change here should be written back to FemConstraintFluidBoundary.cpp if (boundaryType == "wall") { ui->labelBoundaryValue->setText(QString::fromUtf8("velocity (m/s)")); ui->tabBasicBoundary->setEnabled(false); pcConstraint->Subtype.setEnums(WallSubtypes); } else if (boundaryType == "interface") { ui->labelBoundaryValue->setText(QString::fromUtf8("value not needed")); ui->tabBasicBoundary->setEnabled(false); pcConstraint->Subtype.setEnums(InterfaceSubtypes); } else if (boundaryType == "freestream") { ui->tabBasicBoundary->setEnabled(false); ui->labelBoundaryValue->setText(QString::fromUtf8("value not needed")); ui->tabBasicBoundary->setEnabled(false); pcConstraint->Subtype.setEnums(FreestreamSubtypes); } else if (boundaryType == "inlet") { ui->tabBasicBoundary->setEnabled(true); pcConstraint->Subtype.setEnums(InletSubtypes); ui->labelBoundaryValue->setText(QString::fromUtf8("Pressure [Pa]")); // default to pressure pcConstraint->Reversed.setValue(true); // inlet must point into volume } else if (boundaryType == "outlet") { ui->tabBasicBoundary->setEnabled(true); pcConstraint->Subtype.setEnums(OutletSubtypes); ui->labelBoundaryValue->setText(QString::fromUtf8("Pressure [Pa]")); pcConstraint->Reversed.setValue(false); // outlet must point outward } else { Base::Console().Message(boundaryType.c_str()); Base::Console().Message("Error: Fluid boundary type is not defined\n"); } //std::string subtypeLabel = boundaryType + std::string(" type"); //ui->labelSubtype->setText(QString::fromUtf8(subtypeLabel)); // too long to show in UI //set subType to default one, the second one as in ConstraintFluidBoundary ui->comboSubtype->setCurrentIndex(1); // each boundary type must have at least 2 subtypes std::vector subtypes = pcConstraint->Subtype.getEnumVector(); initComboBox(ui->comboSubtype, subtypes, pcConstraint->Subtype.getValueAsString()); ui->tabWidget->setCurrentIndex(0); updateSubtypeUI(); } void TaskFemConstraintFluidBoundary::updateSubtypeUI() { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); //* Subtype PropertyEnumeration is updated if BoundaryType is changed std::string boundaryType = pcConstraint->BoundaryType.getValueAsString(); std::string subtype = Base::Tools::toStdString(ui->comboSubtype->currentText()); if (boundaryType == "inlet" || boundaryType == "outlet") { ui->tabBasicBoundary->setEnabled(true); if (subtype == "totalPressure" || subtype == "staticPressure"){ ui->labelBoundaryValue->setText(QString::fromUtf8("pressure [Pa]")); ui->buttonDirection->setEnabled(false); ui->lineDirection->setEnabled(false); } else if (subtype == "uniformVelocity") { ui->labelBoundaryValue->setText(QString::fromUtf8("velocity [m/s]")); ui->buttonDirection->setEnabled(true); ui->lineDirection->setEnabled(true); } else if (subtype == "massFlowrate") { ui->labelBoundaryValue->setText(QString::fromUtf8("flowrate [kg/s]")); ui->buttonDirection->setEnabled(false); ui->lineDirection->setEnabled(false); } else if (subtype == "volumetricFlowRate") { ui->labelBoundaryValue->setText(QString::fromUtf8("flowrate [m3/s]")); ui->buttonDirection->setEnabled(false); ui->lineDirection->setEnabled(false); } else { ui->labelBoundaryValue->setText(QString::fromUtf8("unspecific")); ui->tabBasicBoundary->setEnabled(false); } } if (boundaryType == "wall") { if (subtype == "moving") { ui->labelBoundaryValue->setText(QString::fromUtf8("moving speed (m/s)")); ui->tabBasicBoundary->setEnabled(true); ui->buttonDirection->setEnabled(false); // moving speed must be parallel to wall ui->lineDirection->setEnabled(false); } else if (subtype == "slip") { ui->labelBoundaryValue->setText(QString::fromUtf8("not needed")); ui->tabBasicBoundary->setEnabled(false); } else if (subtype == "partialSlip") { ui->labelBoundaryValue->setText(QString::fromUtf8("slip ratio(0~1)")); ui->tabBasicBoundary->setEnabled(true); ui->buttonDirection->setEnabled(false); ui->lineDirection->setEnabled(false); } else { ui->labelBoundaryValue->setText(QString::fromUtf8("unspecific")); ui->tabBasicBoundary->setEnabled(false); } } if (boundaryType == "interface") { ui->tabBasicBoundary->setEnabled(false); //show help text int iInterface = ui->comboSubtype->currentIndex(); ui->labelHelpText->setText(tr(InterfaceSubtypeHelpTexts[iInterface])); } } /// hide/disable UI only happend in constructor, update helptext and valuetext here void TaskFemConstraintFluidBoundary::updateTurbulenceUI() { ui->labelHelpText->setText(tr(TurbulenceSpecificationHelpTexts[ui->comboTurbulenceSpecification->currentIndex()])); } void TaskFemConstraintFluidBoundary::updateThermalBoundaryUI() { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); std::string thermalBoundaryType = pcConstraint->ThermalBoundaryType.getValueAsString(); //to hide/disable UI according to subtype ui->labelHelpText->setText(tr(ThermalBoundaryHelpTexts[ui->comboThermalBoundaryType->currentIndex()])); } void TaskFemConstraintFluidBoundary::updateSelectionUI() { if (ui->listReferences->model()->rowCount() == 0) { // Go into reference selection mode if no reference has been selected yet onButtonReference(true); return; } /** not needed for fluid boundary, as it must be Face for 3D part, * Edge type boundary is needed for 2D CFD, but it is not supported yet std::string ref = ui->listReferences->item(0)->text().toStdString(); int pos = ref.find_last_of(":"); if (ref.substr(pos+1, 6) == "Vertex") ui->labelForce->setText(tr("Point load")); else if (ref.substr(pos+1, 4) == "Edge") ui->labelForce->setText(tr("Line load")); else if (ref.substr(pos+1, 4) == "Face") ui->labelForce->setText(tr("Area load")); */ } void TaskFemConstraintFluidBoundary::onSelectionChanged(const Gui::SelectionChanges& msg) { if (msg.Type == Gui::SelectionChanges::AddSelection) { // Don't allow selection in other document if (strcmp(msg.pDocName, ConstraintView->getObject()->getDocument()->getName()) != 0) return; if (!msg.pSubName || msg.pSubName[0] == '\0') return; std::string subName(msg.pSubName); if (selectionMode == selnone) return; std::vector references(1,subName); Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); App::DocumentObject* obj = ConstraintView->getObject()->getDocument()->getObject(msg.pObjectName); Part::Feature* feat = static_cast(obj); TopoDS_Shape ref = feat->Shape.getShape().getSubShape(subName.c_str()); //* string conversion: toStdString()/fromStdString() if (selectionMode == selref) { std::vector Objects = pcConstraint->References.getValues(); std::vector SubElements = pcConstraint->References.getSubValues(); // Ensure we don't have mixed reference types if (SubElements.size() > 0) { if (subName.substr(0,4) != SubElements.front().substr(0,4)) { QMessageBox::warning(this, tr("Selection error"), tr("Mixed shape types are not possible. Use a second constraint instead")); return; } } else { if ((subName.substr(0,4) != "Face")) { QMessageBox::warning(this, tr("Selection error"), tr("Only faces can be picked for fluid boundary")); return; } } // Avoid duplicates std::size_t pos = 0; for (; pos < Objects.size(); pos++) { if (obj == Objects[pos]) { break; } } if (pos != Objects.size()) { if (subName == SubElements[pos]) { return; } } // add the new reference Objects.push_back(obj); SubElements.push_back(subName); pcConstraint->References.setValues(Objects,SubElements); ui->listReferences->addItem(makeRefText(obj, subName)); // Turn off reference selection mode onButtonReference(false); } else if (selectionMode == seldir) { if (subName.substr(0,4) == "Face") { if (!Fem::Tools::isPlanar(TopoDS::Face(ref))) { QMessageBox::warning(this, tr("Selection error"), tr("Only planar faces can be picked")); return; } } else { QMessageBox::warning(this, tr("Selection error"), tr("Only faces can be picked")); return; } pcConstraint->Direction.setValue(obj, references); ui->lineDirection->setText(makeRefText(obj, subName)); // Turn off direction selection mode onButtonDirection(false); } Gui::Selection().clearSelection(); updateSelectionUI(); } } void TaskFemConstraintFluidBoundary::onBoundaryTypeChanged(void) { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); pcConstraint->BoundaryType.setValue(ui->comboBoundaryType->currentIndex()); updateBoundaryTypeUI(); ConstraintView->updateData(&pcConstraint->BoundaryType); //force a 3D redraw // bug: cube normal is not correct in redraw, redraw is correct only after close task panel // see note of If ConstraintView->updateData(): the arrows are not oriented correctly initially // because the NormalDirection has not been calculated yet } void TaskFemConstraintFluidBoundary::onSubtypeChanged(void) { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); pcConstraint->Subtype.setValue(ui->comboSubtype->currentIndex()); updateSubtypeUI(); } void TaskFemConstraintFluidBoundary::onBoundaryValueChanged(double) { //left empty for future extension } void TaskFemConstraintFluidBoundary::onTurbulenceSpecificationChanged(void) { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); pcConstraint->TurbulenceSpecification.setValue(ui->comboTurbulenceSpecification->currentIndex()); updateTurbulenceUI(); } void TaskFemConstraintFluidBoundary::onThermalBoundaryTypeChanged(void) { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); pcConstraint->ThermalBoundaryType.setValue(ui->comboThermalBoundaryType->currentIndex()); updateThermalBoundaryUI(); } void TaskFemConstraintFluidBoundary::onReferenceDeleted() { int row = ui->listReferences->currentIndex().row(); TaskFemConstraint::onReferenceDeleted(row); ui->listReferences->model()->removeRow(row); ui->listReferences->setCurrentRow(0, QItemSelectionModel::ClearAndSelect); } void TaskFemConstraintFluidBoundary::onButtonDirection(const bool pressed) { if (pressed) { selectionMode = seldir; } else { selectionMode = selnone; } ui->buttonDirection->setChecked(pressed); Gui::Selection().clearSelection(); } void TaskFemConstraintFluidBoundary::onCheckReverse(const bool pressed) { Fem::ConstraintFluidBoundary* pcConstraint = static_cast(ConstraintView->getObject()); pcConstraint->Reversed.setValue(pressed); } std::string TaskFemConstraintFluidBoundary::getBoundaryType(void) const { return Base::Tools::toStdString(ui->comboBoundaryType->currentText()); } std::string TaskFemConstraintFluidBoundary::getSubtype(void) const { return Base::Tools::toStdString(ui->comboSubtype->currentText()); } double TaskFemConstraintFluidBoundary::getBoundaryValue(void) const { return ui->spinBoundaryValue->value(); } std::string TaskFemConstraintFluidBoundary::getTurbulenceModel(void) const { if(pTurbulenceModel){ return pTurbulenceModel->getValueAsString(); } else{ return "wall"; } } std::string TaskFemConstraintFluidBoundary::getTurbulenceSpecification(void) const { return Base::Tools::toStdString(ui->comboTurbulenceSpecification->currentText()); } double TaskFemConstraintFluidBoundary::getTurbulentIntensityValue(void) const { return ui->spinTurbulentIntensityValue->value(); } double TaskFemConstraintFluidBoundary::getTurbulentLengthValue(void) const { return ui->spinTurbulentLengthValue->value(); } bool TaskFemConstraintFluidBoundary::getHeatTransfering(void) const { if(pHeatTransfering){ return pHeatTransfering->getValue(); } else{ return false; } } std::string TaskFemConstraintFluidBoundary::getThermalBoundaryType(void) const { return Base::Tools::toStdString(ui->comboThermalBoundaryType->currentText()); } double TaskFemConstraintFluidBoundary::getTemperatureValue(void) const { return ui->spinTemperatureValue->value(); } double TaskFemConstraintFluidBoundary::getHeatFluxValue(void) const { return ui->spinHeatFluxValue->value(); } double TaskFemConstraintFluidBoundary::getHTCoeffValue(void) const { return ui->spinHTCoeffValue->value(); } const std::string TaskFemConstraintFluidBoundary::getReferences() const { int rows = ui->listReferences->model()->rowCount(); std::vector items; for (int r = 0; r < rows; r++) items.push_back(ui->listReferences->item(r)->text().toStdString()); return TaskFemConstraint::getReferences(items); } const std::string TaskFemConstraintFluidBoundary::getDirectionName(void) const { std::string dir = ui->lineDirection->text().toStdString(); if (dir.empty()) return ""; int pos = dir.find_last_of(":"); return dir.substr(0, pos).c_str(); } const std::string TaskFemConstraintFluidBoundary::getDirectionObject(void) const { std::string dir = ui->lineDirection->text().toStdString(); if (dir.empty()) return ""; int pos = dir.find_last_of(":"); return dir.substr(pos+1).c_str(); } bool TaskFemConstraintFluidBoundary::getReverse() const { return ui->checkReverse->isChecked(); } TaskFemConstraintFluidBoundary::~TaskFemConstraintFluidBoundary() { delete ui; } void TaskFemConstraintFluidBoundary::changeEvent(QEvent *e) { TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { ui->spinBoundaryValue->blockSignals(true); //more ui widget? those UI are does not support tr yet! ui->retranslateUi(proxy); ui->spinBoundaryValue->blockSignals(false); } } //************************************************************************** //************************************************************************** // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgFemConstraintFluidBoundary::TaskDlgFemConstraintFluidBoundary(ViewProviderFemConstraintFluidBoundary *ConstraintView) { this->ConstraintView = ConstraintView; assert(ConstraintView); this->parameter = new TaskFemConstraintFluidBoundary(ConstraintView);; Content.push_back(parameter); } //==== calls from the TaskView =============================================================== void TaskDlgFemConstraintFluidBoundary::open() { // a transaction is already open at creation time of the panel if (!Gui::Command::hasPendingCommand()) { QString msg = QObject::tr("Constraint fluid boundary"); Gui::Command::openCommand((const char*)msg.toUtf8()); } } bool TaskDlgFemConstraintFluidBoundary::accept() { std::string name = ConstraintView->getObject()->getNameInDocument(); const TaskFemConstraintFluidBoundary* boundary = static_cast(parameter); try { //Gui::Command::openCommand("Fluid boundary condition changed"); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.BoundaryType = '%s'", name.c_str(), boundary->getBoundaryType().c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Subtype = '%s'", name.c_str(), boundary->getSubtype().c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.BoundaryValue = %f", name.c_str(), boundary->getBoundaryValue()); std::string dirname = boundary->getDirectionName().data(); std::string dirobj = boundary->getDirectionObject().data(); if (!dirname.empty()) { QString buf = QString::fromUtf8("(App.ActiveDocument.%1,[\"%2\"])"); buf = buf.arg(QString::fromStdString(dirname)); buf = buf.arg(QString::fromStdString(dirobj)); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Direction = %s", name.c_str(), buf.toStdString().c_str()); } else { Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Direction = None", name.c_str()); } //Reverse control is done at BoundaryType selection, this UI is hiden from user //Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %s", name.c_str(), boundary->getReverse() ? "True" : "False"); std::string scale = "1"; scale = boundary->getScale(); //OvG: determine modified scale Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Scale = %s", name.c_str(), scale.c_str()); //OvG: implement modified scale //solver specific setting Fem::FemSolverObject* pcSolver = NULL; if (FemGui::ActiveAnalysisObserver::instance()->hasActiveObject()) { Fem::FemAnalysis* pcAnalysis = FemGui::ActiveAnalysisObserver::instance()->getActiveObject(); //Fem::FemSolverObject is derived from DocumentObject std::vector fem = pcAnalysis->Member.getValues(); for (std::vector::iterator it = fem.begin(); it != fem.end(); ++it) { if ((*it)->getTypeId().isDerivedFrom(Fem::FemSolverObject::getClassTypeId())) pcSolver = static_cast(*it); } } if (pcSolver) { App::PropertyBool* pHeatTransfering = NULL; App::PropertyEnumeration* pTurbulenceModel = NULL; pHeatTransfering = static_cast(pcSolver->getPropertyByName("HeatTransfering")); pTurbulenceModel = static_cast(pcSolver->getPropertyByName("TurbulenceModel")); if (pHeatTransfering && pHeatTransfering->getValue()) { Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ThermalBoundaryType = '%s'",name.c_str(), boundary->getThermalBoundaryType().c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.TemperatureValue = %f",name.c_str(), boundary->getTemperatureValue()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.HeatFluxValue = %f",name.c_str(), boundary->getHeatFluxValue()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.HTCoeffValue = %f",name.c_str(), boundary->getHTCoeffValue()); } if (pTurbulenceModel && std::string(pTurbulenceModel->getValueAsString()) != "laminar") { //update turbulence and thermal boundary settings, only if those models are activated Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.TurbulenceSpecification = '%s'",name.c_str(), boundary->getTurbulenceSpecification().c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.TurbulentIntensityValue = %f",name.c_str(), boundary->getTurbulentIntensityValue()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.TurbulentLengthValue = %f",name.c_str(), boundary->getTurbulentLengthValue()); } } //rename document obj according to boundaryType: } catch (const Base::Exception& e) { QMessageBox::warning(parameter, tr("Input error"), QString::fromLatin1(e.what())); return false; } return TaskDlgFemConstraint::accept(); } bool TaskDlgFemConstraintFluidBoundary::reject() { // roll back the changes Gui::Command::abortCommand(); Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); Gui::Command::updateActive(); return true; } #include "moc_TaskFemConstraintFluidBoundary.cpp"