-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hide boundary points in figure #391
Conversation
This PR removed the unrelated files in #361 and set the shown points as a variable of Euler1DApp. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Provide an option to select the amount of data to plot. It can serve as a way to fall back to the original behavior.
- Rename
plot_point
toxindices
. - Fix CI errors.
Please fix the CI failures. A prominent one is test failures on the array size: https://github.com/solvcon/modmesh/actions/runs/10025477375/job/27708689299?pr=391#step:11:285 :
=================================== FAILURES ===================================
____________________ ShockTubeTC.test_field_with_numerical _____________________
self = <test_onedim_euler.ShockTubeTC testMethod=test_field_with_numerical>
def test_field_with_numerical(self):
self.st.build_numerical(xmin=-1, xmax=1, ncoord=21,
time_increment=0.05)
self.st.build_field(t=0.0)
self.assertIsInstance(self.st.svr, euler1d.Euler1DSolver)
> self.assertEqual(len(self.st.coord), 11)
E AssertionError: 9 != 11
tests/test_onedim_euler.py:110: AssertionError
=========================== short test summary info ============================
FAILED tests/test_onedim_euler.py::ShockTubeTC::test_field_with_numerical - AssertionError: 9 != 11
=================== 1 failed, 181 passed, 5 skipped in 6.72s ===================
make: *** [pytest] Error 1
The test fails because you changed the length of the array.
modmesh/app/euler1d.py
Outdated
@@ -511,6 +511,8 @@ def set_solver_config(self): | |||
self.interval = self.solver_config.get_var("timer_interval", "value") | |||
self.max_steps = self.solver_config.get_var("max_steps", "value") | |||
self.profiling = self.solver_config.get_var("profiling", "value") | |||
ncoord = self.solver_config.get_var("ncoord", "value") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@j8xixo12 With this PR I realized that self.solver_config.get_var()
is too wordy. The lengthy API makes it hard to quickly write and understand code.
Please propose a new design of SolverConfig
and PlotConfig
in the discussions. We can probably consider __getattr__()
or __getitem__()
@Gene0315 please provide an option to keep existing behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Gene0315 You can use the inline comment for focused discussions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@j8xixo12 Any comments?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will create a discussion and propose a new design in the discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I will create a discussion and propose a new design in the discussion.
Thanks, @j8xixo12 . Maybe creating an issue describing what we know and may be done can help.
modmesh/app/euler1d.py
Outdated
@@ -511,6 +511,8 @@ def set_solver_config(self): | |||
self.interval = self.solver_config.get_var("timer_interval", "value") | |||
self.max_steps = self.solver_config.get_var("max_steps", "value") | |||
self.profiling = self.solver_config.get_var("profiling", "value") | |||
ncoord = self.solver_config.get_var("ncoord", "value") | |||
self.plot_point = np.linspace(2, (ncoord - 3), num=((ncoord - 3) // 2), dtype=int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A convention of short-living temporary variables is _
. The two lines can be changed to:
_ = self.solver_config.get_var("ncoord", "value")
self.xindices = np.linspace(2, (_ - 3), num=((_ - 3) // 2), dtype=int)
plot_point
is not a good attribute name because the content is not points but indices of the coordinate (1D point) arrays.
Are these two the same questions? Do you mean to provide it as an option such as "ncoord" or "max step" in qt window?
It is ok.
But I don't know how to check whether I solve the CI error correctly. Maybe I can create a PR in my own repo again before I upload the new code here? |
Yes they are similar. No, the options only need to be in the code. We do not need them to be in the GUI yet.
You can turn on Github Actions in your own repository and you will see the CI runs when you push to your repository. You do not need a PR for the CI runs in your repository. You should also run the tests locally to reproduce the failures on your development machine for fixing them. |
I'm so confused how to set the
How can I run the check tests in my laptop? Is it feasable to run the |
Something like: def set_solver_config(self, keep_edge=False):
# ...
if keep_edge:
# create self.xindices including the edge points.
else:
_ = self.solver_config.get_var("ncoord", "value")
self.xindices = np.linspace(2, (_ - 3), num=((_ - 3) // 2), dtype=int) In this way you can allow a configuring function to turn on If you want to make the option available in GUI, the flag
The Line 116 in 6a9888d
They are used in Github Actions too. |
@yungyuc I passed all the checks finally! But, I don't know what I have to do next. Could you give me some tips? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yungyuc I passed all the checks finally! But, I don't know what I have to do next. Could you give me some tips?
Congratulations! Passing all checks means your code starts to work. Then we can start code review.
Please address the following points:
- Remove the redundant
startup.py
. - Use a more specific code comment than "Use the numerical solver".
- Remove all unnecessary add/removal/change of blank lines and white spaces.
- It makes more sense to calculate
num
fromstart
andstop
. - There should be only one call to
np.linspace()
. The conditional (if/else) should be used to calculate the arguments to the helper. - The
xindices
attribute should be created in the initialization helperEuler1DSolver.init_solver()
of the objectself.svr
. - Reduce the change to the code in the function
update_lines()
.
@j8xixo12 Could you please also help take a look?
startup.py
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is redundant file, please remove.
modmesh/onedim/euler1d.py
Outdated
self.svr.xindices = np.linspace( | ||
2, (_ - 3), num=((_ - 3) // 2), dtype=int | ||
) | ||
# Use the numerical solver. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please be more specific about what you meant. "Use the numerical solver" is not a clear statement.
modmesh/onedim/euler1d.py
Outdated
""" | ||
Populate the field data using the analytical solution. | ||
|
||
:param t: | ||
:param coord: If None, take the coordinate from the numerical solver. | ||
:return: None | ||
""" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This insertion of a blank line is not necessary. Do you introduce unnecessary/unrelated change of blank lines and whitespaces in a patch (i.e., checkins/PR).
tests/test_onedim_euler.py
Outdated
@@ -105,7 +105,7 @@ def test_field_without_numerical(self): | |||
def test_field_with_numerical(self): | |||
self.st.build_numerical(xmin=-1, xmax=1, ncoord=21, | |||
time_increment=0.05) | |||
self.st.build_field(t=0.0) | |||
self.st.build_field(t=0.0, keep_edge=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix of the unit tests by the addition of the single argument is good.
modmesh/onedim/euler1d.py
Outdated
if None is coord: | ||
coord = self.svr.coord[::2] # Use the numerical solver. | ||
_ = self.svr.ncoord |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This 9 lines of code is mouthy. Please use the follow code instead (please make proper adjustment if needed because I didn't test it myself):
_ = self.svr.ncoord
start = 0 if keep_edge else 2
stop = _ - stop - 1
num = # It makes more sense to calculate from start and stop
xindices = np.linspace(start, stop, num=num, dtype='int32')
modmesh/onedim/euler1d.py
Outdated
_ = self.svr.ncoord | ||
if keep_edge: | ||
self.svr.xindices = np.linspace( | ||
0, (_ - 1), num=((_ + 1) // 2), dtype=int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes more sense to calculate num
from start
and stop
.
modmesh/onedim/euler1d.py
Outdated
coord = self.svr.coord[::2] # Use the numerical solver. | ||
_ = self.svr.ncoord | ||
if keep_edge: | ||
self.svr.xindices = np.linspace( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The xindices
attribute should be created in the initialization helper Euler1DSolver.init_solver()
of the object self.svr
:
modmesh/modmesh/onedim/euler1d.py
Line 36 in 214b474
def init_solver(xmin, xmax, ncoord, time_increment, gamma): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not add attributes outside the class. It will be very difficult for a maintainer to keep track of where attributes are added, if they are not created in an organized way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do not add attributes outside the class. It will be very difficult for a maintainer to keep track of where attributes are added, if they are not created in an organized way.
@yungyuc I agree that we shouldn't add attributes outside the class, but I failed to create the xindices
in the Euler1DCore
modmesh/modmesh/onedim/euler1d.py
Line 38 in 214b474
svr = _impl.Euler1DCore(ncoord=ncoord, time_increment=time_increment) |
I tried to add the
xindices
invoid Euler1DCore::initialize_data(size_t ncoord) |
like
m_coord
inm_coord = SimpleArray<double>(/*length*/ ncoord); |
but I'm confused how to add it because I cannot decide its size in the begining.
Or, maybe I misunderstand what you want me to do? Can you give me some suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.svr
is a Euler1DSolver
object. You can create xindices
after
modmesh/modmesh/onedim/euler1d.py
Line 28 in 214b474
self._core = self.init_solver(xmin, xmax, ncoord, time_increment, |
The code may be like:
def __init__(self, xmin, xmax, ncoord, time_increment=0.05):
self._core = self.init_solver(xmin, xmax, ncoord, time_increment,
gamma=1.4)
self.xindices = ...
# gamma is 1.4 for air.
You may consider to let Euler1DSolver.__init__()
take a new argument for keep_edge
, if necessary.
modmesh/app/euler1d.py
Outdated
internal_energy[::2])) | ||
self.entropy.update(adata=self.st.entropy_field, | ||
ndata=self.st.svr.entropy[::2]) | ||
self.density.update( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please simplify the code like:
_s = self.st.svr.xindices
self.density.update(adata=self.st.density_field,
ndata=self.st.svr.density[_s])
In this way, you do not change the original code by too much. It will be easier to keep track of the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change of line breaking is not necessary for updating the slicing (from [::2]
to [_s]
). Please revert it to the original style.
That is, since the original style is:
self.pressure.update(adata=self.st.pressure_field,
ndata=self.st.svr.pressure[::2])
instead of writing (with the different line breaking):
self.pressure.update(
adata=self.st.density_field,
ndata=self.st.svr.density[_s]
)
write
self.pressure.update(adata=self.st.pressure_field,
ndata=self.st.svr.pressure[_s])
The unnecessary change will baffle future maintainers. Style matters. Don't change the style when changing the logic, and vice versa. Change of logic and that of style should not take place at the same time.
@yungyuc I tried to revise the code like what you mentioned above. Could you take a look at it? I'm not sure whether the code is fine now. Thank you! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some old issues were not handled and there are also new issues. Please fix.
-
app/euler1d.py:747
: Do not change the line breaking (style). This has been request in the previous review. -
onedim/euler1d.py:324
: Do not create a new object forxindices
inself.svr
when updating the value. Instead, force to use the existing one by writingself.svr.xindices[...]
. -
onedim/euler1d.py:320
: Why duplicate code?
modmesh/app/euler1d.py
Outdated
internal_energy[::2])) | ||
self.entropy.update(adata=self.st.entropy_field, | ||
ndata=self.st.svr.entropy[::2]) | ||
self.density.update( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change of line breaking is not necessary for updating the slicing (from [::2]
to [_s]
). Please revert it to the original style.
That is, since the original style is:
self.pressure.update(adata=self.st.pressure_field,
ndata=self.st.svr.pressure[::2])
instead of writing (with the different line breaking):
self.pressure.update(
adata=self.st.density_field,
ndata=self.st.svr.density[_s]
)
write
self.pressure.update(adata=self.st.pressure_field,
ndata=self.st.svr.pressure[_s])
The unnecessary change will baffle future maintainers. Style matters. Don't change the style when changing the logic, and vice versa. Change of logic and that of style should not take place at the same time.
modmesh/onedim/euler1d.py
Outdated
start = 0 if keep_edge else 2 | ||
stop = _ if keep_edge else (_ - 2) | ||
num = (stop - start) // 2 + 1 | ||
self.svr.xindices = np.linspace(start, stop, num, dtype='int32') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Write self.svr.xindices[...] = np.linspace(start, stop, num, dtype='int32')
. Note that the first ...
in []
is ellipsis. By using the ellipsis, you are using the xindices
created in the solver object instead of creating a new one and replacing the existing one.
modmesh/onedim/euler1d.py
Outdated
if None is coord: | ||
coord = self.svr.coord[::2] # Use the numerical solver. | ||
if coord is None: | ||
_ = self.svr.ncoord - 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you need to repeat the same code here and in line 32?
Sorry, in my understanding, passing
In previous code, I want to know the size of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. It now looks perfect!
Following the issue #361
The PR hides the boundary points.
Features: The plotting hides the unreasonable points on the boundary.
Strength: It makes the figure look nicer without changing the solution data.
Weakness: It is better to calculate the correct values on the boundary and show them on the boundary.