diff --git a/comp/fespace.cpp b/comp/fespace.cpp index 1102330e2..15d501b21 100644 --- a/comp/fespace.cpp +++ b/comp/fespace.cpp @@ -87,15 +87,6 @@ namespace ngcomp lot of new non-zero entries in the matrix!\n" << endl; // else *testout << "\n (" << order << ") flag dgjumps is not used!" << endl; - if (autoupdate) - { - ma->updateSignal.Connect(this, [this]() - { - this->Update(); - this->FinalizeUpdate(); - }); - } - if(flags.NumListFlagDefined("directsolverdomains")) { directsolverclustered.SetSize(ama->GetNDomains()); diff --git a/comp/gridfunction.cpp b/comp/gridfunction.cpp index 5ce2d891c..23bd987eb 100644 --- a/comp/gridfunction.cpp +++ b/comp/gridfunction.cpp @@ -86,8 +86,6 @@ namespace ngcomp visual = !flags.GetDefineFlag ("novisual"); multidim = int (flags.GetNumFlag ("multidim", 1)); autoupdate = flags.GetDefineFlag ("autoupdate"); - if (autoupdate) - fes->updateSignal.Connect(this, [this]() { this->Update(); }); auto comp_space = dynamic_pointer_cast(fespace); if(comp_space) diff --git a/comp/python_comp.cpp b/comp/python_comp.cpp index 3426b46a8..935600253 100644 --- a/comp/python_comp.cpp +++ b/comp/python_comp.cpp @@ -37,8 +37,6 @@ namespace ngcomp } - - class PyNumProc : public NumProc { public: @@ -564,6 +562,7 @@ kwargs : kwargs fes->FinalizeUpdate(); if (!spaces[0]->DoesAutoUpdate()) fes->SetDoSubspaceUpdate(true); + connect_auto_update(fes.get()); return shared_ptr{fes}; // py::cast(*instance).attr("flags") = bpflags; }), @@ -579,6 +578,7 @@ kwargs : kwargs auto fes = CreateFESpace (type, ma, flags); fes->Update(); fes->FinalizeUpdate(); + connect_auto_update(fes.get()); return fes; }), py::arg("type"), py::arg("mesh"), @@ -962,7 +962,7 @@ coupling_type : ngsolve.comp.COUPLING_TYPE .def_property_readonly("couplingtype", [] (shared_ptr self) { return FlatArray(self->CouplingTypes()); }) - .def_property_readonly("autoupdate", [] (shared_ptr self) {self->DoesAutoUpdate();}) + .def_property_readonly("autoupdate", [] (shared_ptr self) {return self->DoesAutoUpdate();}) .def ("GetFE", [](shared_ptr self, ElementId ei) -> py::object { auto fe = shared_ptr (&self->GetFE(ei, global_alloc)); @@ -1117,7 +1117,7 @@ rho : ngsolve.fem.CoefficientFunction flags.SetFlag ("dgjumps", space1->UsesDGCoupling() || space2->UsesDGCoupling()); if (space1->DoesAutoUpdate() != space2->DoesAutoUpdate()) - throw Exception("Both spaces need same autoupdate setting."); + throw Exception("Both spaces need same autoupdate setting."); flags.SetFlag ("autoupdate", space1->DoesAutoUpdate()); if(space1->LowOrderFESpacePtr() && space2->LowOrderFESpacePtr()) @@ -1137,7 +1137,8 @@ rho : ngsolve.fem.CoefficientFunction productspace->Update(); productspace->FinalizeUpdate(); if (!space1->DoesAutoUpdate()) - productspace->SetDoSubspaceUpdate(true); + productspace->SetDoSubspaceUpdate(true); + connect_auto_update(productspace.get()); return productspace; }) @@ -1153,7 +1154,8 @@ rho : ngsolve.fem.CoefficientFunction productspace->Update(); productspace->FinalizeUpdate(); if (!space->DoesAutoUpdate()) - productspace->SetDoSubspaceUpdate(true); + productspace->SetDoSubspaceUpdate(true); + connect_auto_update(productspace.get()); return productspace; }) @@ -1212,6 +1214,7 @@ rho : ngsolve.fem.CoefficientFunction fes->FinalizeUpdate(); if (!autoupdate) fes->SetDoSubspaceUpdate(true); + connect_auto_update(fes.get()); return fes; })) .def(py::pickle([] (py::object pyfes) @@ -1311,7 +1314,8 @@ component : int vecspace->Update(); vecspace->FinalizeUpdate(); if (!space->DoesAutoUpdate()) - vecspace->SetDoSubspaceUpdate(true); + vecspace->SetDoSubspaceUpdate(true); + connect_auto_update(vecspace.get()); return vecspace; }),py::arg("space"), py::arg("dim")=nullopt) .def(py::pickle([] (py::object pyfes) @@ -1347,7 +1351,8 @@ component : int matspace->Update(); matspace->FinalizeUpdate(); if (!space->DoesAutoUpdate()) - matspace->SetDoSubspaceUpdate(true); + matspace->SetDoSubspaceUpdate(true); + connect_auto_update(matspace.get()); return matspace; }),py::arg("space"), py::arg("dim")=nullopt, py::arg("symmetric")=false, py::arg("deviatoric")=false) ; @@ -1500,6 +1505,8 @@ used_idnrs : list of int = None perfes = make_shared(fes,flags,a_used_idnrs); perfes->Update(); perfes->FinalizeUpdate(); + // MR: is autoupdate contained in flags? + connect_auto_update(perfes.get()); return perfes; }), py::arg("fespace"), py::arg("phase")=nullopt, py::arg("use_idnrs")=py::list()) @@ -1578,10 +1585,13 @@ BND : boolean or None disc_class .def(py::init([disc_class] (shared_ptr & fes, py::kwargs kwargs) { - auto flags = CreateFlagsFromKwArgs(kwargs, disc_class); + auto flags = CreateFlagsFromKwArgs(kwargs, disc_class); + // MR: Is this logic correct or should it be required that fes does autoupdate? + flags.SetFlag("autoupdate", flags.GetDefineFlagX("autoupdate").IsTrue() || fes->DoesAutoUpdate()); auto dcfes = make_shared(fes, flags); dcfes->Update(); dcfes->FinalizeUpdate(); + connect_auto_update(dcfes.get()); return dcfes; }), py::arg("fespace")) /* @@ -1640,9 +1650,12 @@ fespace : ngsolve.comp.FESpace .def(py::init([disc_class] (shared_ptr & fes, py::kwargs kwargs) { auto flags = CreateFlagsFromKwArgs(kwargs, disc_class); + // MR: Is this logic correct or should it be required that fes does autoupdate? + flags.SetFlag("autoupdate", flags.GetDefineFlagX("autoupdate").IsTrue() || fes->DoesAutoUpdate()); auto hiddenfes = make_shared(fes, flags); hiddenfes->Update(); hiddenfes->FinalizeUpdate(); + connect_auto_update(hiddenfes.get()); return hiddenfes; }), py::arg("fespace")) ; @@ -1656,9 +1669,12 @@ fespace : ngsolve.comp.FESpace .def(py::init([] (shared_ptr & fes) { Flags flags = fes->GetFlags(); + // MR: Is this logic correct or should it be required that fes does autoupdate? + flags.SetFlag("autoupdate", flags.GetDefineFlagX("autoupdate").IsTrue() || fes->DoesAutoUpdate()); auto refes = make_shared(fes, flags); refes->Update(); refes->FinalizeUpdate(); + connect_auto_update(refes.get()); return refes; }), py::arg("fespace")) /* @@ -1732,6 +1748,8 @@ active_dofs : BitArray or None dynamic_pointer_cast(ret)->SetActiveDofs(py::extract>(active_dofs)()); ret->Update(); ret->FinalizeUpdate(); + // MR: Does ret "inherit" the autoupdate from "fes" + connect_auto_update(ret.get()); return ret; }), py::arg("fespace"), py::arg("active_dofs")=DummyArgument()) .def("SetActiveDofs", [](CompressedFESpace & self, shared_ptr active_dofs) @@ -1865,6 +1883,7 @@ active_dofs : BitArray or None flags.SetFlag("novisual"); auto gf = CreateGridFunction(fes, name, flags); gf->Update(); + connect_auto_update(gf.get()); return gf; }), py::arg("space"), py::arg("name")="gfu", "creates a gridfunction in finite element space") @@ -1941,6 +1960,7 @@ active_dofs : BitArray or None "the finite element space") .def("Update", [](GF& self) { self.Update(); }, "update vector size to finite element space dimension after mesh refinement") + .def_property_readonly("autoupdate", [] (shared_ptr self) {return self->DoesAutoUpdate();}) .def("Save", [](GF& self, string filename, bool parallel) { diff --git a/comp/python_comp.hpp b/comp/python_comp.hpp index 894d4dde0..38a51e4eb 100644 --- a/comp/python_comp.hpp +++ b/comp/python_comp.hpp @@ -49,9 +49,28 @@ namespace ngcomp state[2].cast()); fes->Update(); fes->FinalizeUpdate(); + // MR: connect_auto_update? return dynamic_pointer_cast(fes); }; + void connect_auto_update(FESpace* fes) { + if (fes->weak_from_this().expired()) + throw Exception("Given pointer is not managed by a shared ptr."); + if (fes->DoesAutoUpdate()) + fes->GetMeshAccess()->updateSignal.Connect(fes, [fes]() + { + fes->Update(); + fes->FinalizeUpdate(); + }); + } + + void connect_auto_update(GridFunction* gf) { + if (gf->weak_from_this().expired()) + throw Exception("Given pointer is not managed by a shared ptr."); + if (gf->DoesAutoUpdate()) + gf->GetFESpace()->updateSignal.Connect(gf, [gf](){ gf->Update(); }); + } + template auto ExportFESpace (py::module & m, string pyname, bool module_local = false) { @@ -69,6 +88,7 @@ namespace ngcomp auto fes = make_shared(ma,flags); fes->Update(); fes->FinalizeUpdate(); + connect_auto_update(fes.get()); return fes; }),py::arg("mesh"))