-
Notifications
You must be signed in to change notification settings - Fork 67
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
Feature improvements for the Model
class
#16
Comments
Thanks for your input. Here are my first thoughts:
So maybe start with 2., 3., possibly 4. Any help is welcome. By the way, I've noticed that your name doesn't appear as a "contributor" on the repo's front page. I think it's because the email address in your |
(1) I did never realizes that names / labels have to be unique. If that's the case then scrap tags altogether at API level. However I suggest the following: There are often calls like names = self.exports()
tags = [str(tag) for tag in self.java.result().export().tags()]
tag = tags[names.index(node)] to extract tags. Sometimes they have no error handling (like this), sometimes they have (ValueError for (3) I'll see what I can come up with. Some remarks: There are different functions which are completely different (Analytical, Interpolation) in their nature and their arguments. I suggest different API functions for each. Also, there are some args which can be set, like reinterpolation or further options. This could be done via **kwargs in python - is this something you are ok with or should they be exposed by args with default values? (4) My thought exactly, however I would just make that (5) Forget that, too specific I think. If you create an export, you need to specify a dataset. This one would create a dataset from a selection. However the selection needs to be in COMSOL, so creating the dataset using the UI is easier anyway, especially since there are many different types of datasets. (6) Before exporting, you need to create the export. Or you can change it by changing the target file (already enabled) or the variables. Since this is again very specific, I do not think it is important. (7) Call PS: I had a different email attached to the pushes. I added this one to git too. |
I did put together an idea of how functions, in this case an interpolation, could be managed. Since this is more like a blueprint to discuss, I will add it here and not create a PR at this point. I added comments with my thoughts on this... # This allows a general edit using kwargs
def function_edit(self, function, **kwargs):
"""Edits any node of a function when the kwargs match"""
# Get the function tags
for tag in self.java.func().tags():
if str(self.java.func(tag).label()) == function:
break
else:
error = f'Function "{function}" does not exist.'
logger.critical(error)
raise LookupError(error)
# Edit with typecast
for keyword, value in kwargs:
# This should catch possible types, see Reference Guide.
# Strings seem to be converted on the fly
if isinstance(value, int):
value = JInt(value)
elif isinstance(value, float):
value = JDouble(value)
elif isinstance(value, bool):
value = JBool(value)
try:
self.java.func(tag).set(keyword, value)
except Exception: # Too general - what is the correct type here
error = f'Can not set function property {keyword}'
logger.warning(error)
# Raise exception?
# This would be the same as already implemented with a slight rename and arg resort
def function_interpolation_load(self, interpolation, file):
"""
Loads an external `file` and assigns its data to the named
`interpolation` function.
"""
for tag in self.java.func().tags():
if str(self.java.func(tag).label()) == interpolation:
break
else:
error = f'Interpolation function "{interpolation}" does not exist.'
logger.critical(error)
raise LookupError(error)
file = Path(file)
logger.info(f'Loading external data from file "{file.name}".')
self.java.func(tag).discardData()
self.java.func(tag).set('filename', f'{file}')
self.java.func(tag).importData()
logger.info('Finished loading external data.')
# This creates the interpolation function. The user would need to check the
# Comsol reference guide for valid kwargs, but the API is fairly compact
def function_interpolation_create(self, name, file, **kwargs):
"""Creates a new interpolation to use down the road"""
tag = f'int_{randint(0, 100)}' # This is probably a bad idea since it can create duplicates
self.java.func().create(tag, 'Interpolation')
self.java.func(tag).label(label)
self.java.func(tag).set('source', 'file')
self.function_interpolation_load(file, name)
# Those are conservative defaults. They can be overwritted using kwargs
# or we remove them from here anyway
self.java.func(tag).set('extrap', 'const')
self.java.func(tag).set('interp', 'neighbor')
if kwargs:
self.function_edit(name, **kwargs)
return name |
Yeah, let's discuss. Figuring out the best API is difficult. Naming things is hard. I often go back an forth. Though once you have a good concept for the API, the implementation almost writes itself. On that note… I will probably once again rename some things that are now in Just so that we're on the same page, the current "release schedule", if there is such a thing, looks kind of like this:
Regarding API design… In the documentation I talk about the scope limitation of this library. That's not a firmly delineated line, we certainly can push further than what we have now. But the reason I mentioned it, is that the basic design of the implementation (I happened to choose) is not suitable to expose all aspects of the Comsol API. That's because the class hierarchy is flat: It's just the Obviously this could be changed. But it would not just be a lot of work, it's also kind of redundant. Because ultimately it would just mirror the class hierarchy of the Comsol Java API. It might add a little bit of flair here and there, like hiding tags and using names instead, but probably not enough to justify such an effort. Plus, it would either break the existing API, or it would be difficult to work around what already exists, because all the "good names" in the Thrameos mentioned in issue #7 that JPype offers functionality to customize Java objects with Python functions. That would be an interesting avenue to explore. But so far I haven't looked into it at all. Just something to keep in mind. There's a chance, at least, it might magically solve a lot of problems. As for this particular idea… Then there's And So, just thinking "out loud" here… In the flat class hierarchy that we have, maybe we should add a This would map strings to Comsol's object hierarchy. It still doesn't cover everything (only properties, not method calls), but it's a step in that direction. An alternative would be to have access methods such as (PS: Comsol exposes a (PPS: Catching |
I can say that it is possible to have many servers running, which are distinguished by their ports. They are (by default) closed when a worker is finished. If this is easy to wrap in several processes - I don't know.
I would suggest you to not got that way. I think - as you also said - this should be the core functionality. COMSOL is, in my opinion, not too clear about which features work with which input data (see my closed issue...there is Coming to the specific code I posted: I think this would be something that is very often used for convenience - so this is why I have suggested it being added, or at least gave an idea of the functionality that I aimed for.
Yes - I suggested to think about a rename - since it will be only applicable to an interpolation.
Agree - see above. But for clarity I opted for a long name.
This could be generalized as a setter for an arbitrary object by name, which would allow a lot of customization with a simple method in python. However there would be some issues that come to my mind:
But coming to
This would be the combination of all this. However when creating it might be difficult to find the right location in the model tree. This goes back to a remark up top where I said that COMSOL it not always to clear about that, e.g. a PS: Found the |
Currently, I do not find a good starting point for improvements which will suit the current package setup and I do not have the time to dig into jpype to get a handle on customization. |
Yeah, I've been busy too. I do think there are good ideas here though. The I think providing a So both of these suggestion would take some time to implement. Not just writing code, also going through the Comsol API documentation and object hierarchy. Though I do think especially the latter is a good starting point, as it's pretty straightforward. It would be pretty much a long |
@max3-2 |
@max3-2 |
@John-Hennig Allright, nice!
on macOS everything (still) is flawless. On windows it seems to run good however there are some strange issues with jpype and pyenv so the testing procedure was not perfect. However on either |
Okay, great, thanks. I don't use pyenv. For the tests I've now run with Python 3.6, 3.7, and 3.8, I just have separate Python installations on my Windows machine. Create a new issue if you can pinpoint the bug. Also, I've created and pinned an issue named "chat" for stuff that doesn't really belong anywhere else. Like, if this pyenv thing remains murky, maybe give more details over there. Not sure I can help, but if it's not a clear bug it may help to discuss it first. |
Model
class
I think the model class can get some extended features. As @John-Hennig stated this should be kept as general as possible, especially since class inheritance allows easy extension. I will just start by listing some features I use often and add some small explanation and either +0- depending on my thoughts if they should be implemented.
I can help implement some / most of the stuff. But I will sit for your input @John-Hennig before...
The text was updated successfully, but these errors were encountered: