FEM: Update multiframe code after review

This commit is contained in:
Stefan Tröger
2025-03-22 09:15:05 +01:00
committed by Benjamin Nauck
parent 713feb5f27
commit b38170cb02
14 changed files with 48 additions and 77 deletions

View File

@@ -36,7 +36,7 @@ PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostBranchFilter, Fem::FemPostFilter);
const char* FemPostBranchFilter::OutputEnums[] = {"Passthrough", "Append", nullptr};
FemPostBranchFilter::FemPostBranchFilter() : Fem::FemPostFilter(), Fem::FemPostGroupExtension()
FemPostBranchFilter::FemPostBranchFilter()
{
FemPostGroupExtension::initExtension(this);
@@ -78,8 +78,6 @@ FemPostBranchFilter::FemPostBranchFilter() : Fem::FemPostFilter(), Fem::FemPostG
setActiveFilterPipeline("passthrough");
}
FemPostBranchFilter::~FemPostBranchFilter() = default;
short FemPostBranchFilter::mustExecute() const
{
if (Mode.isTouched()) {
@@ -102,17 +100,17 @@ void FemPostBranchFilter::setupPipeline()
// prepare output filter: we make all connections new!
m_append->RemoveAllInputConnections(0);
FemPostFilter* filter = NULL;
FemPostFilter* filter = nullptr;
for (auto& obj : objs) {
// prepare the filter: make all connections new
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(obj);
auto* nextFilter = static_cast<FemPostFilter*>(obj);
nextFilter->getFilterInput()->RemoveAllInputConnections(0);
// handle input modes
if (Mode.getValue() == Fem::PostGroupMode::Serial) {
// serial: the next filter gets the previous output, the first one gets our input
if (filter == NULL) {
if (!filter) {
nextFilter->getFilterInput()->SetInputConnection(m_passthrough->GetOutputPort());
} else {
nextFilter->getFilterInput()->SetInputConnection(filter->getFilterOutput()->GetOutputPort());
@@ -209,7 +207,7 @@ void FemPostBranchFilter::filterChanged(FemPostFilter* filter)
}
}
void FemPostBranchFilter::filterPipelineChanged(FemPostFilter*) {
void FemPostBranchFilter::filterPipelineChanged([[maybe_unused]] FemPostFilter* postfilter) {
// one of our filters has changed its active pipeline. We need to reconnect it properly.
// As we are cheap we just reconnect everything
// TODO: Do more efficiently

View File

@@ -42,7 +42,6 @@ class FemExport FemPostBranchFilter: public Fem::FemPostFilter, public FemPostGr
public:
/// Constructor
FemPostBranchFilter();
~FemPostBranchFilter() override;
App::PropertyEnumeration Output;

View File

@@ -10,7 +10,7 @@
FatherInclude="Mod/Fem/App/FemPostObjectPy.h"
FatherNamespace="Fem">
<Documentation>
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
<Author Licence="LGPL" Name="Stefan Tröger" EMail="stefantroeger@gmx.net" />
<UserDocu>The FemPostBranch class.</UserDocu>
</Documentation>
<Methode Name="getFilter">

View File

@@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (c) 2017 Werner Mayer <wmayer[at]users.sourceforge.net> *
* Copyright (c) 2025 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *

View File

@@ -72,7 +72,7 @@ void FemPostFilter::setActiveFilterPipeline(std::string name)
if (m_activePipeline != name && isValid()) {
// disable all inputs of current pipeline
if (m_activePipeline != "" and m_pipelines.find( m_activePipeline ) != m_pipelines.end()) {
if (m_activePipeline != "" && m_pipelines.find( m_activePipeline ) != m_pipelines.end()) {
m_pipelines[m_activePipeline].source->RemoveAllInputConnections(0);
}
@@ -964,21 +964,9 @@ void FemPostContoursFilter::refreshFields()
Field.setValue(m_fields);
// search if the current field is in the available ones and set it
<<<<<<< HEAD
const auto it = std::ranges::find(FieldsArray, fieldName);
if (!fieldName.empty() && it != FieldsArray.end()) {
Field.setValue(fieldName.c_str());
}
else {
m_blockPropertyChanges = false;
// select the first field
Field.setValue(long(0));
fieldName = Field.getValueAsString();
=======
// Note: list could be empty and hence Field invalid
if (Field.isValid()) {
std::vector<std::string>::iterator it =
std::find(FieldsArray.begin(), FieldsArray.end(), fieldName);
const auto it = std::ranges::find(FieldsArray, fieldName);
if (!fieldName.empty() && it != FieldsArray.end()) {
Field.setValue(fieldName.c_str());
}
@@ -987,7 +975,6 @@ void FemPostContoursFilter::refreshFields()
// select the first field
Field.setValue(long(0));
}
>>>>>>> cf27d7e05b (FEM: Multistep test fix for vtk 7.x)
}
m_blockPropertyChanges = false;

View File

@@ -142,11 +142,7 @@ FemPostObject* FemPostGroupExtension::getLastPostObject()
bool FemPostGroupExtension::holdsPostObject(FemPostObject* obj)
{
for (const auto& group_obj : Group.getValues()) {
if (group_obj == obj) {
return true;
}
}
return false;
return std::ranges::any_of(Group.getValues(), [obj](const auto& group_obj) {
return group_obj == obj;
});
}

View File

@@ -138,7 +138,7 @@ int FemFrameSourceAlgorithm::RequestInformation(vtkInformation* reqInfo,
std::vector<double> frames = getFrameValues();
if (frames.empty()) {
// no frames, default info is sfficient
// no frames, default info is sufficient
return 1;
}
@@ -190,8 +190,8 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation*,
frame = std::abs(frame - time);
}
auto it = std::min_element(std::begin(frames), std::end(frames));
idx = std::distance(std::begin(frames), it);
auto it = std::ranges::min_element(frames);
idx = std::distance(frames.begin(), it);
}
auto block = multiblock->GetBlock(idx);
@@ -202,8 +202,6 @@ int FemFrameSourceAlgorithm::RequestData(vtkInformation*,
PROPERTY_SOURCE_WITH_EXTENSIONS(Fem::FemPostPipeline, Fem::FemPostObject)
FemPostPipeline::FemPostPipeline()
: FemPostObject()
, FemPostGroupExtension()
{
FemPostGroupExtension::initExtension(this);
@@ -220,8 +218,6 @@ FemPostPipeline::FemPostPipeline()
m_transform_filter->SetInputConnection(m_source_algorithm->GetOutputPort(0));
}
FemPostPipeline::~FemPostPipeline() = default;
vtkDataSet* FemPostPipeline::getDataSet()
{
@@ -458,8 +454,8 @@ void FemPostPipeline::onChanged(const Property* prop)
value = frames[Frame.getValue()];
}
for (const auto& obj : Group.getValues()) {
if (obj->isDerivedFrom<FemPostFilter>()) {
static_cast<Fem::FemPostFilter*>(obj)->Frame.setValue(value);
if (auto* postFilter = Base::freecad_dynamic_cast<FemPostFilter>(obj)) {
postFilter->Frame.setValue(value);
}
}
// pipeline data updated!
@@ -478,7 +474,7 @@ void FemPostPipeline::onChanged(const Property* prop)
return;
}
FemPostFilter* filter = NULL;
FemPostFilter* filter = nullptr;
for (auto& obj : objs) {
// prepare the filter: make all connections new
@@ -494,7 +490,7 @@ void FemPostPipeline::onChanged(const Property* prop)
}
else {
// serial: the next filter gets the previous output, the first one gets our input
if (filter == NULL) {
if (!filter) {
nextFilter->getFilterInput()->SetInputConnection(
m_transform_filter->GetOutputPort(0));
}

View File

@@ -71,7 +71,6 @@ class FemExport FemPostPipeline: public Fem::FemPostObject, public Fem::FemPostG
public:
/// Constructor
FemPostPipeline();
~FemPostPipeline() override;
App::PropertyEnumeration Frame;

View File

@@ -10,7 +10,7 @@
FatherInclude="Mod/Fem/App/FemPostObjectPy.h"
FatherNamespace="Fem">
<Documentation>
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
<Author Licence="LGPL" Name="Stefan Tröger" EMail="stefantroeger@gmx.net" />
<UserDocu>The FemPostPipeline class.</UserDocu>
</Documentation>
<Methode Name="read">

View File

@@ -45,20 +45,13 @@ std::string FemPostPipelinePy::representation() const
PyObject* FemPostPipelinePy::read(PyObject* args)
{
char* Name;
if (PyArg_ParseTuple(args, "et", "utf-8", &Name)) {
getFemPostPipelinePtr()->read(Base::FileInfo(Name));
PyMem_Free(Name);
Py_Return;
}
PyObject *files;
PyObject *values = nullptr;
PyObject *unitobj = nullptr;
const char* value_type;
if (PyArg_ParseTuple(args, "O|OO!s", &files, &values, &(Base::UnitPy::Type), &unitobj, &value_type)) {
if (values == nullptr) {
if (!values) {
// single argument version was called!
@@ -69,7 +62,7 @@ PyObject* FemPostPipelinePy::read(PyObject* args)
const char* path = PyUnicode_AsUTF8(files);
getFemPostPipelinePtr()->read(Base::FileInfo(path));
}
else if (values != nullptr && unitobj != nullptr) {
else if (values && unitobj) {
//multistep version!
@@ -120,7 +113,6 @@ PyObject* FemPostPipelinePy::read(PyObject* args)
Py_Return;
}
}
return nullptr;
}
@@ -143,7 +135,7 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
if (PyArg_ParseTuple(args, "O|OO!s", &py, &list, &(Base::UnitPy::Type), &unitobj, &value_type)) {
if (list == nullptr) {
if (!list) {
// single argument version!
@@ -160,14 +152,14 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
getFemPostPipelinePtr()->load(static_cast<FemResultObject*>(obj));
Py_Return;
}
else if (list != nullptr && unitobj != nullptr) {
else if (list && unitobj) {
//multistep version!
if ( !(PyTuple_Check(py) || PyList_Check(py)) ||
!(PyTuple_Check(list) || PyList_Check(list)) ) {
std::string error = std::string("Result and value must be list of ResultObjet and number respectively.");
std::string error = std::string("Result and value must be list of ResultObject and number respectively.");
throw Base::TypeError(error);
}
@@ -214,10 +206,13 @@ PyObject* FemPostPipelinePy::load(PyObject* args)
// Finally call the c++ function!
getFemPostPipelinePtr()->load(results, values, unit, step_type);
Py_Return;
} else {
std::string error = std::string("Multistep load requries 4 arguments: ResultList, ValueList, unit, type");
throw Base::TypeError(error);
}
}
Py_Return;
return nullptr;
}

View File

@@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* Copyright (c) 2025 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *

View File

@@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (c) 2015 Stefan Tröger <stefantroeger@gmx.net> *
* Copyright (c) 2025 Stefan Tröger <stefantroeger@gmx.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *

View File

@@ -646,13 +646,10 @@ def makePostVtkResult(doc, result_data, name="VtkResult"):
needed for a multistep result: [results_list, value_list, unit, description]
"""
print(result_data)
Pipeline_Name = "Pipeline_" + name
obj = doc.addObject("Fem::FemPostPipeline", Pipeline_Name)
print("load")
obj.load(*result_data)
print("load done")
if FreeCAD.GuiUp:
obj.ViewObject.SelectionStyle = "BoundBox"
# to assure the user sees something, set the default to Surface

View File

@@ -227,18 +227,22 @@ def importFrd(filename, analysis=None, result_name_prefix="", result_analysis_ty
# we have collected all result objects, lets create the multistep result pipeline
if number_of_increments > 1:
# figure out type and unit
unit = FreeCAD.Units.Unit("")
description = "Unknown"
if result_analysis_type == "frequency":
unit = FreeCAD.Units.Frequency
description = "Eigenmode"
elif result_analysis_type == "buckling":
description = "Buckling factor"
elif result_analysis_type == "thermomech":
unit = FreeCAD.Units.TimeSpan
description = "Timesteps"
elif result_analysis_type == "static":
description = "Load factor"
match result_analysis_type:
case "frequency":
unit = FreeCAD.Units.Frequency
description = "Eigenmode"
case "buckling":
unit = FreeCAD.Units.Unit()
description = "Buckling factor"
case "thermomech":
unit = FreeCAD.Units.TimeSpan
description = "Timesteps"
case "static":
unit = FreeCAD.Units.Unit()
description = "Load factor"
case _:
unit = FreeCAD.Units.Unit()
description = "Unknown"
setupPipeline(doc, analysis, results_name, [multistep_result, multistep_value, unit, description])