Open dbrakenhoff opened 12 months ago
if addtomodel:
in LineSinkHoBase and maybe in other Base elements that are part of compound elementsself.lslist
with refined elements, do not create new element copies.refine
to refine_level
, default is 1 (no refine).
This is related to #89, but discusses a different style of refinement, subdividing lines into N segments. This is probably especially useful for Inhoms (e.g. BuildingPits).
The implementation requires some thought, hence this long and detailed post... This is just one idea, but maybe serves as a good starting point for figuring out the best way forward.
Refining elements into segments
The general idea is to give certain elements a
Element._refine()
method. This method is called ininitialize()
ifrefine=True
for that particular element. The_refine()
method takesn
as an argument, which splits line segments into $N$ segments, and returns a list of new smaller (shorter?) elements.Some requirements:
refine=True/False
flag in the element.initialize()
orsolve()
should always give the same answer, obviously.Limitations:
Some example code:
Distinguishing between user-added elements and internally added elements
For this to work, there needs to be a distinction between elements specified by the user and elements that are created internally when refine is called.
Model.elements
includes all elements added to a Model by the userModel.aq.inhoms
includes all inhoms added to a a Model by the userInhom.elementlist
is the list of all elements belonging to a certain inhom for the computationModel.elementlist
is the list of all elements for the computationModel.aq.inhomlist
is the list of inhoms used for computationAll elements and inhoms will need an
addtomodel
option, to prevent internally created elements from getting added to the user element list. Some elements already have this, but now more will need this option.The different types of elements
Workflow
For elements
Model.add_element()
adds element toModel.elements
Model.initialize()
Model.elementlist
is populated in this step, for collecting all computation elements.addtomodel=False
) that are added toModel.elementlist
for the computation.model.aq.elementlist
.Model.elementlist
andModel.aq.elementlist
start empty at the start of every solve.For inhoms
Model.aq.add_inhom()
adds inhom to the user-inhom listModel.aq.inhoms
.Model.aq.initialize()
eventually callsinhom.create_elements()
create_elements
creates elements that are added to the computation listModel.elementlist
. These elements are added manually, and not by the constructors of the elements themselves (addtomodel=False
).model.aq.inhoms
, but added to computation inhom list:model.aq.inhomlist
).create_elements
on refined or original Inhom.Refinement based on proximity vertices
Link to issue #89.
Additional automatic refinement is desirable when elements lie close to one another, e.g. a well near an impermeable wall. The modifications presented here should also make it possible to implement this style of refinement.
One challenge is that the current segment-splitting refinement will modify the vertices of elements in the computation. These refined elements only become available in the initialize function, so not all vertices may be known yet in the initialize phase. That means a second loop through the element list is required in
Model.initialize()
to further refine them based on vertices.Questions
The user-specified elements can be different from the actual elements used in the computation. Any methods called on the original element will either not work or be incorrect.
Perhaps we can catch this with the refine flag? If refine=True, the element was not used in the computation, and therefore should throw an error/warning if any methods are called on it?
some code to illustrate:
hls.discharge() # <-- this is not the element that was used in the computation! ml.elementlist[0].discharge() # <-- this would be the refined element that was used
Should there be a model-level refine option, e.g.
ml.solve(refine=True)
? If so, would this approach make sense:refine=None
, use Element level options (default)refine=False
, override Element level options with Falserefine=True
, override Element level optinos with Truerefine=<int>
, add this as an option to set refinement level globally?Some elements had an
if self.addtomodel: self.aq.add_element(self)
in the initialize function. Is there ever a reason not to add an element to the aquifer computation list in initialize?An alternative to creating a new refined inhomogeneity or compound element instance (e.g. HeadLineSinkString) is to refine the element in-place, prior to creating the sub-elements. The advantage is that the original reference to the object can be used for computation, as it will be used in the calculation. The downside is that you lose a copy of the original user-specified element.