import mmf_setup
mmf_setup.nbinit()
This cell adds /home/docs/checkouts/readthedocs.org/user_builds/gpe/checkouts/latest/src to your path, and contains some definitions for equations and some CSS for styling the notebook. If things look a bit strange, please try the following:
- Choose "Trust Notebook" from the "File" menu.
- Re-execute this cell.
- Reload the notebook.
Programming Interfaces#
To make programming easier and ensure that future versions of the code work well, we defined some programming interfaces to glue various pieces together. This system consists of several interrelated parts.
States#
At the lowest level are the various IState interfaces defined in the pytimeode project. Objects that implement these interfaces can be used with the various evolvers provided by the pytimeode class. At a minimum, the user must define the IStateMinimal interface (though much of this is provided by various mixin classes) and one of the following:
IStateForABMEvolvers: This essentially requires that the user provide acompute_dy_dt(dy)method which computes the time-derivative of the state and stores it indy. This allows one to use thepytimeode.evolvers.EvolverABMevolver for high-precision time-evolution. If the basis resolution is chosen correctly, one should be able to evolve with a timestep of up todt=0.5*state.t_scalewith values of0.2being quite typical. (Ifdtmust be significantly smaller, you probably do not have sufficient resolution in your state.) One advantage of this evolver is that, if it converges, it is generally accurate. Once convergence is broken, the evolver usually blows up, raising floating-point errors (NaNs, Inf, etc.).IStateForSplitEvolvers: This essentially requires that the user provide two methods:apply_exp_K(dt)andapply_exp_V(dt, state)which apply the exponential of the kinetic and potential operators over time intervaldtto the state. This requires the true matrix exponential of these operators, so (modulo clever reasoning) requires that these operators be diagonalizable in either the position (for \(\op{V}\)) or momentum (for \(\op{K}\)) bases. If these can be implement, this gives a low-order, but unitary evolution scheme that can be used with large time-steps to get a qualitative (but usually not quantitative) idea of what is happening. Large time-steps can be used here with imaginary time cooling to good effect. This can also be invaluable when designing a problem and for debugging.
Here we define a variety of states that implement various physical scenarios. For example, we have different states for different bases – periodic, axial, tubes, etc. – and for different types of problems such as single-component or multi-component mixtures.
To complement these, we provide a set of experiment classes which are intended to define an experimental protocol that can be used
Experiment#
Reference#
Here are the programmatically generated interfaces:
IStateForABMEvolvers#
from mmfutils.interface import describe_interface
from pytimeode import interfaces
[I 03:37:50 root] Patching zope.interface.document.asReStructuredText to format code
[I 03:37:51 numexpr.utils] NumExpr defaulting to 2 threads.
display(describe_interface(interfaces.IStateForABMEvolvers))
IStateForABMEvolvers
Interface required by ABM and similar integration based evolvers.
These evolvers are very general, requiring only the ability for the problem to compute $dy/dt$.
This interface extends:
o IStateAttributes:
Methods:
compute_dy_dt(dy) -- Return dy/dt at time self.t using the memory in state dy.
Warning: dy is simply recycled memory that should be used if possible. It contains no useful information. (I.e., compute dy/dt for the current state y == self.
IStateForSplitEvolvers#
display(describe_interface(interfaces.IStateForSplitEvolvers))
IStateForSplitEvolvers
Interface required by Split Operator evolvers.
These evolvers assume the problem can be split into two operators - $K$ (kinetic energy) and $V$ (potential energy) so that $i dy/dt = (K+V)y$. The method requires that each of these operators be exponentiated. The approach uses a Trotter decomposition that provides higher order accuracy, but requires evaluation of the potentials at an intermediate time.
This interface requires that the apply_exp_V() method accept another state object which should be used for calculating any non-linear terms in $V$ which are state dependent.
If your problem is linear (i.e. $V$ depends only on time, not on the state as in the case of the usual linear Schrodinger equation), then you should set the linear attribute which will improve performance (but do not use this for non-linear problems or the order of convergence will be reduced).
This interface extends:
o IStateAttributes:
linear -- Is the problem linear?Methods:
apply_exp_K(dt) -- Apply $e^{-i K dt}$ in place
apply_exp_V(dt, state) -- Apply $e^{-i V dt}$ in place using state for any nonlinear dependence in V. (Linear problems should ignore state.)
IStateMinimal#
display(describe_interface(interfaces.IStateMinimal))
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 display(describe_interface(interfaces.IStateMinimal))
AttributeError: module 'pytimeode.interfaces' has no attribute 'IStateMinimal'
IState#
display(describe_interface(interfaces.IState))
<string>:71: (SEVERE/4) Unexpected section title.
Arguments
---------
---------------------------------------------------------------------------
SystemMessage Traceback (most recent call last)
Cell In[7], line 1
----> 1 display(describe_interface(interfaces.IState))
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/mmfutils/interface.py:207, in describe_interface(interface, format)
204 if format.lower() == "rst":
205 return rst
--> 207 html = core.publish_string(rst, writer=writer).decode()
208 if format.lower() == "html":
209 return html
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/core.py:460, in publish_string(source, source_path, destination_path, reader, reader_name, parser, parser_name, writer, writer_name, settings, settings_spec, settings_overrides, config_section, enable_exit_status)
436 def publish_string(source, source_path=None, destination_path=None,
437 reader=None, reader_name='standalone',
438 parser=None, parser_name='restructuredtext',
(...) 441 settings_overrides=None, config_section=None,
442 enable_exit_status=False):
443 """
444 Set up & run a `Publisher` for programmatic use with string I/O.
445
(...) 458 https://docutils.sourceforge.io/docs/user/config.html#output-encoding
459 """
--> 460 output, publisher = publish_programmatically(
461 source_class=io.StringInput, source=source, source_path=source_path,
462 destination_class=io.StringOutput,
463 destination=None, destination_path=destination_path,
464 reader=reader, reader_name=reader_name,
465 parser=parser, parser_name=parser_name,
466 writer=writer, writer_name=writer_name,
467 settings=settings, settings_spec=settings_spec,
468 settings_overrides=settings_overrides,
469 config_section=config_section,
470 enable_exit_status=enable_exit_status)
471 return output
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/core.py:722, in publish_programmatically(source_class, source, source_path, destination_class, destination, destination_path, reader, reader_name, parser, parser_name, writer, writer_name, settings, settings_spec, settings_overrides, config_section, enable_exit_status)
720 publisher.set_source(source, source_path)
721 publisher.set_destination(destination, destination_path)
--> 722 output = publisher.publish(enable_exit_status=enable_exit_status)
723 return output, publisher
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/core.py:234, in Publisher.publish(self, argv, usage, description, settings_spec, settings_overrides, config_section, enable_exit_status)
232 self.set_io()
233 self.prompt()
--> 234 self.document = self.reader.read(self.source, self.parser,
235 self.settings)
236 self.apply_transforms()
237 output = self.writer.write(self.document, self.destination)
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/readers/__init__.py:70, in Reader.read(self, source, parser, settings)
68 self.settings = settings
69 self.input = self.source.read()
---> 70 self.parse()
71 return self.document
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/readers/__init__.py:76, in Reader.parse(self)
74 """Parse `self.input` into a document tree."""
75 self.document = document = self.new_document()
---> 76 self.parser.parse(self.input, document)
77 document.current_source = document.current_line = None
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/__init__.py:184, in Parser.parse(self, inputstring, document)
182 break
183 else:
--> 184 self.statemachine.run(inputlines, document, inliner=self.inliner)
185 # restore the "default" default role after parsing a document
186 if '' in roles._roles:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:169, in RSTStateMachine.run(self, input_lines, document, input_offset, match_titles, inliner)
167 self.reporter = self.memo.reporter
168 self.node = document
--> 169 results = StateMachineWS.run(self, input_lines, input_offset,
170 input_source=document['source'])
171 assert results == [], 'RSTStateMachine.run() results should be empty!'
172 self.node = self.memo = None
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/statemachine.py:233, in StateMachine.run(self, input_lines, input_offset, context, input_source, initial_state)
228 source, offset = self.input_lines.info(
229 self.line_offset)
230 print(f'\nStateMachine.run: line '
231 f'(source={source!r}, offset={offset!r}):\n'
232 f'| {self.line}', file=sys.stderr)
--> 233 context, next_state, result = self.check_line(
234 context, state, transitions)
235 except EOFError:
236 if self.debug:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/statemachine.py:445, in StateMachine.check_line(self, context, state, transitions)
441 if self.debug:
442 print('\nStateMachine.check_line: Matched transition '
443 f'"{name}" in state "{state.__class__.__name__}".',
444 file=sys.stderr)
--> 445 return method(match, context, next_state)
446 else:
447 if self.debug:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:1170, in Body.indent(self, match, context, next_state)
1167 """Block quote."""
1168 (indented, indent, line_offset, blank_finish
1169 ) = self.state_machine.get_indented()
-> 1170 elements = self.block_quote(indented, line_offset)
1171 self.parent += elements
1172 if not blank_finish:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:1187, in Body.block_quote(self, indented, line_offset)
1180 (blockquote.source, blockquote.line
1181 ) = self.state_machine.get_source_and_line(line_offset+1)
1182 (blockquote_lines,
1183 attribution_lines,
1184 attribution_offset,
1185 indented,
1186 new_line_offset) = self.split_attribution(indented, line_offset)
-> 1187 self.nested_parse(blockquote_lines, line_offset, blockquote)
1188 elements.append(blockquote)
1189 if attribution_lines:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:279, in RSTState.nested_parse(self, block, input_offset, node, match_titles, state_machine_class, state_machine_kwargs)
276 if not state_machine:
277 state_machine = state_machine_class(debug=self.debug,
278 **state_machine_kwargs)
--> 279 state_machine.run(block, input_offset, memo=self.memo,
280 node=node, match_titles=match_titles)
281 if use_default == 2:
282 self.nested_sm_cache.append(state_machine)
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:195, in NestedStateMachine.run(self, input_lines, input_offset, memo, node, match_titles)
193 self.language = memo.language
194 self.node = node
--> 195 results = StateMachineWS.run(self, input_lines, input_offset)
196 assert results == [], ('NestedStateMachine.run() results should be '
197 'empty!')
198 return results
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/statemachine.py:233, in StateMachine.run(self, input_lines, input_offset, context, input_source, initial_state)
228 source, offset = self.input_lines.info(
229 self.line_offset)
230 print(f'\nStateMachine.run: line '
231 f'(source={source!r}, offset={offset!r}):\n'
232 f'| {self.line}', file=sys.stderr)
--> 233 context, next_state, result = self.check_line(
234 context, state, transitions)
235 except EOFError:
236 if self.debug:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/statemachine.py:445, in StateMachine.check_line(self, context, state, transitions)
441 if self.debug:
442 print('\nStateMachine.check_line: Matched transition '
443 f'"{name}" in state "{state.__class__.__name__}".',
444 file=sys.stderr)
--> 445 return method(match, context, next_state)
446 else:
447 if self.debug:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:1170, in Body.indent(self, match, context, next_state)
1167 """Block quote."""
1168 (indented, indent, line_offset, blank_finish
1169 ) = self.state_machine.get_indented()
-> 1170 elements = self.block_quote(indented, line_offset)
1171 self.parent += elements
1172 if not blank_finish:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:1187, in Body.block_quote(self, indented, line_offset)
1180 (blockquote.source, blockquote.line
1181 ) = self.state_machine.get_source_and_line(line_offset+1)
1182 (blockquote_lines,
1183 attribution_lines,
1184 attribution_offset,
1185 indented,
1186 new_line_offset) = self.split_attribution(indented, line_offset)
-> 1187 self.nested_parse(blockquote_lines, line_offset, blockquote)
1188 elements.append(blockquote)
1189 if attribution_lines:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:279, in RSTState.nested_parse(self, block, input_offset, node, match_titles, state_machine_class, state_machine_kwargs)
276 if not state_machine:
277 state_machine = state_machine_class(debug=self.debug,
278 **state_machine_kwargs)
--> 279 state_machine.run(block, input_offset, memo=self.memo,
280 node=node, match_titles=match_titles)
281 if use_default == 2:
282 self.nested_sm_cache.append(state_machine)
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:195, in NestedStateMachine.run(self, input_lines, input_offset, memo, node, match_titles)
193 self.language = memo.language
194 self.node = node
--> 195 results = StateMachineWS.run(self, input_lines, input_offset)
196 assert results == [], ('NestedStateMachine.run() results should be '
197 'empty!')
198 return results
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/statemachine.py:233, in StateMachine.run(self, input_lines, input_offset, context, input_source, initial_state)
228 source, offset = self.input_lines.info(
229 self.line_offset)
230 print(f'\nStateMachine.run: line '
231 f'(source={source!r}, offset={offset!r}):\n'
232 f'| {self.line}', file=sys.stderr)
--> 233 context, next_state, result = self.check_line(
234 context, state, transitions)
235 except EOFError:
236 if self.debug:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/statemachine.py:445, in StateMachine.check_line(self, context, state, transitions)
441 if self.debug:
442 print('\nStateMachine.check_line: Matched transition '
443 f'"{name}" in state "{state.__class__.__name__}".',
444 file=sys.stderr)
--> 445 return method(match, context, next_state)
446 else:
447 if self.debug:
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/parsers/rst/states.py:2781, in Text.underline(self, match, context, next_state)
2776 src, srcline = self.state_machine.get_source_and_line()
2777 # TODO: why is abs_line_number() == srcline+1
2778 # if the error is in a table (try with test_tables.py)?
2779 # print("get_source_and_line", srcline)
2780 # print("abs_line_number", self.state_machine.abs_line_number())
-> 2781 msg = self.reporter.severe(
2782 'Unexpected section title.',
2783 nodes.literal_block(blocktext, blocktext),
2784 source=src, line=srcline)
2785 self.parent += messages
2786 self.parent += msg
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/utils/__init__.py:239, in Reporter.severe(self, *args, **kwargs)
233 def severe(self, *args, **kwargs):
234 """
235 Level-4, "SEVERE": a severe error that must be addressed. If ignored,
236 the output will contain severe errors. Typically level-4 system
237 messages are turned into exceptions which halt processing.
238 """
--> 239 return self.system_message(self.SEVERE_LEVEL, *args, **kwargs)
File ~/checkouts/readthedocs.org/user_builds/gpe/conda/latest/lib/python3.14/site-packages/docutils/utils/__init__.py:197, in Reporter.system_message(self, level, message, *children, **kwargs)
195 self.stream.write(msg.astext() + '\n')
196 if level >= self.halt_level:
--> 197 raise SystemMessage(msg, level)
198 if level > self.DEBUG_LEVEL or self.debug_flag:
199 self.notify_observers(msg)
SystemMessage: <string>:71: (SEVERE/4) Unexpected section title.
Arguments
---------