Skip to content

Commit

Permalink
Refactored evaluation of global expressions.
Browse files Browse the repository at this point in the history
In parametric sweeps where the number of time steps depends on the
parameter, the number of time steps returned always corresponded
to the first outer solution, i.e. the first parameter value. In
evaluations of other outer solutions, the additional time steps were
then missing. See issue MPh-py#112.

We now use an `EvalGlobal` feature instead of a `Global` evaluation
feature, and call `computeResult` instead of `getData`. This fixes
the issue, though it is not clear (to me) from the Comsol API
documentation why the two feature types and method calls behave
differently.

https://doc.comsol.com/6.1/doc/com.comsol.help.comsol/api/com/comsol/model/NumericalFeature.html
  • Loading branch information
john-hen committed Feb 5, 2023
1 parent b405dfb commit 74d99a9
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
18 changes: 10 additions & 8 deletions mph/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def evaluate(self, expression, unit=None, dataset=None,
raise RuntimeError(error)

# Try to perform a global evaluation, which may fail.
eval = (self/'evaluations').create('Global')
eval = (self/'evaluations').create('EvalGlobal')
eval.property('expr', expression)
if unit:
eval.property('unit', unit)
Expand All @@ -536,26 +536,28 @@ def evaluate(self, expression, unit=None, dataset=None,
try:
log.debug('Trying global evaluation.')
java = eval.java
results = array(java.getData())
results = array(java.computeResult())
if java.isComplex():
results = results.astype('complex')
results += 1j * array(java.getImagData())
eval.remove()
results = results[0].astype('complex') + 1j*results[1]
else:
results = results[0]
log.info('Finished global evaluation.')
if inner is None:
pass
elif inner == 'first':
results = results[:, 0, :]
results = results[0]
elif inner == 'last':
results = results[:, -1, :]
results = results[-1]
else:
if isinstance(inner, list):
inner = array(inner)
results = results[:, inner-1, :]
results = results[inner-1]
return results.squeeze()
# Move on if this fails. Seems to not be a global expression then.
except Exception:
log.debug('Global evaluation failed. Moving on.')
finally:
eval.remove()

# For particle datasets, create an "EvalPoint" feature.
if dataset.type() == 'Particle':
Expand Down
7 changes: 7 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,13 @@ def test_evaluate():
D = model.evaluate(expression, unit, dataset, outer=2)
assert (D[0] == Df).all()
assert (D[-1] == Dl).all()
# Test varying time steps in parameter sweep. See issue #112.
study = model/'studies'/'sweep'
(study/'time-dependent').property('tlist', 'range(0, 0.01/d[1/mm], 1)')
model.solve(study)
assert len(model.evaluate('t', 's', 'parametric sweep', outer=1)) == 101
assert len(model.evaluate('t', 's', 'parametric sweep', outer=2)) == 201
assert len(model.evaluate('t', 's', 'parametric sweep', outer=3)) == 301
# Test evaluation of complex-valued global expressions.
U = model.evaluate('U')
z = model.evaluate('U + j*U')
Expand Down

0 comments on commit 74d99a9

Please sign in to comment.