text:
# NAP-4: Asynchronous slicing¶

Author

Andy Sweet <andrewdsweet@gmail.com>, Jun Xi Ni, Eric Perlman, Kim Pevey

Created

2022-06-23

Resolution

https://github.com/napari/napari/pull/5052

Resolved

2022-09-19

Status

Accepted

Type

Standards Track

Version effective

0.5

## Abstract¶

Slicing a layer in napari generates a partial view of the layer’s data based on the dimension slider positions and the current field of view.

This project has two major goals.

1. Slice layers asynchronously to keep napari responsive while allowing for slow slicing.

2. Improve the logic of slicing layers to help developers better understand how it works and unlock new feature development.

We propose a lock-free asynchronous solution that uses Python’s built-in concurrent.futures module and exploits napari’s main event loop. For each slice, an immutable shallow copy of all the required input to slicing is collected on the main thread and is then processed on a separate single-threaded executor. When the slice task is finished, we notify vispy and Qt objects back on the main thread so they can be safely updated. This approach allows us to gradually introduce asynchronous slicing to napari layer by layer without breaking other functionality that relies on existing layer slice state.

## Motivation and scope¶

Currently, all slicing in napari is performed synchronously. For example, if a dimension slider is moved, napari waits to slice a layer before updating the canvas. When slicing layers is slow, this blocking behavior makes interacting with data difficult and napari may be reported as not responding by the host operating system.

There are two main reasons why slicing can be slow.

1. Some layer specific slicing operations perform non-trivial calculations (e.g. points).

2. The layer data is read lazily (i.e. it is not in RAM) and latency from the source may be non-negligible (e.g. stored remotely, napari-omero plugin).

By slicing asynchronously, we can keep napari responsive while allowing for slow slicing operations. We could also consider optimizing napari to make (1) less of a problem, but that is outside the scope of this project.

Introducing asynchrony to software often complicates program flow and logic. However, the existing technical design of slicing is already complicated and often causes issues for developers.

• Layers have too much state 1 2 3.

• The logic is hard to understand and debug 4.

• The names of the classes are not self-explanatory 5.

Some of these issues were caused by a previous effort around asynchronous slicing in an effort to keep it isolated from the core code base. By contrast, our approach in this project is to redesign slicing in napari to provide a solid foundation for asychronous slicing and related future work like multi-canvas and multi-scale slicing.

### Goals¶

To summarize the scope of this project, we define a few high level goals. Each goal has many prioritized features where P0 is a must-have, P1 is a should-have, and P2 is a could-have. Some of these goals may already be achieved by napari in its current form, but are captured here to prevent any regression caused by this work.

#### 1. Keep responding when slicing slow data¶

• P0. When moving a dimension slider, the slider can still be controlled so that I can navigate to the desired location.

• Slider can be moved when data is in the middle of loading.

• Slider location does not return to position of last loaded slice after it was moved to a different position.

• P0. When the slider is dragged, only slice at some positions so that I don’t wait for unwanted intermediate slicing positions.

• Once slider is moved, wait before performing slicing operation, and cancel any prior pending slices (i.e. be lazy).

• If we can reliably infer that slicing will be fast (e.g. data is a numpy array), consider skipping this delay.

• P0. When slicing fails, I am notified so that I can understand what went wrong.

• May want to limit the number of notifications (e.g. lost network connection for remote data).

• P1. When moving a dimension slider and the slice doesn’t immediately load, I am notified that it is being generated, so that I am aware that my action is being handled.

• Show visual cue to identify the specific layer(s) that are loading in the case where one layer loads faster than another.

#### 2. Clean up slice state and logic in layers¶

• P0. Encapsulate the slice input and output state for each layer type, so that I can quickly and clearly identify those.

• Minimize number of (nested) classes per layer-type (e.g. ImageSlice, ImageSliceData, ImageView, ImageLoader).

• P0. Simplify the program flow of slicing, so that developing and debugging against allows for faster implementation.

• Reduce the complexity of the call stack associated with slicing a layer.

• The implementation details for some layer/data types might be complex (e.g. multi-scale image), but the high level logic should be simple.

• P1. Move the slice state off the layer, so that its attributes only represent the whole data.

• Layer may still have a function to get a slice.

• May need alternatives to access currently private state, though doesn’t necessarily need to be in the Layer (e.g. a plugin with an ND layer, that gets interaction data from 3D visualization , needs some way to get that data back to ND).

• P2. Store multiple slices associated with each layer, so that I can cache previously generated slices.

• Pick a default cache size that should not strain most machines (e.g. 0-1GB).

• Make cache size a user defined preference.

#### 3. Measure slicing latencies on representative examples¶

• P0. Define representative examples that currently cause desirable behavior in napari, so that I can check that async slicing does not degrade those.

• E.g. 2D slice of a 3D image layer where all data fits in RAM, but not VRAM.

• P0. Define representative examples that currently cause undesirable behavior in napari, so that I can check that async slicing improves those.

• E.g. 2D slice of a 3D points layer where all data fits in RAM, but not VRAM.

• E.g. 2D slice of a 3D image layer where all data is not on local storage.

• P0. Define slicing benchmarks, so that I can understand if my changes impact overall timing or memory usage.

• E.g. Do not increase the latency of generating a single slice more than 10%.

• E.g. Decrease the latency of dealing with 25 slice requests over 1 second by 50%.

• P1. Log specific slicing latencies, so that I can summarize important measurements beyond granular profile timings.

• Latency logs are local only (i.e. not sent/stored remotely).

• Add an easy way for users to enable writing these latency measurements.

### Non-goals¶

To help clarify the scope, we also define some things that were are not explicit goals of this project and briefly explain why they were omitted.

• Make a single slicing operation faster.

• Useful, but can be done independently of this work.

• Improve slicing functionality.

• Useful, but can be done independently of this work.

• Make async a toggleable setting (i.e. async is always on).

• May complicate the program flow of slicing.

• May still automatically infer that slicing can be synchronously.

• When a slice doesn’t immediately load, show a low level of detail version of it, so that I can preview what is upcoming.

• Requires a low level of detail version to exist.

• Should be part of a to-be-defined multi-scale project.

• Store multiple slices associated with each layer, so that I can easily implement a multi-canvas mode for napari.

• Should be part of a to-be-defined multi-canvas project.

• Solutions for goal (2) should not block this in the future.

• Open, save, or process layers asynchronously.

• More related to plugin execution.

• Lazily load parts of data based on the canvas’ current field of view.

• An optimization that is dependent on specific data formats.

• Identify and assign dimensions to layers and transforms.

• Should be part of a to-be-defined dimensions project.

• Solutions for goal (2) should not block this in the future.

• Thick slices of non-visualized dimensions.

• Currently being prototyped in 6.

• Solutions for goal (2) should not block this in the future.

• Keep the experimental async fork working.

• Nice to have, but should not put too much effort into this.

• May want to remove it to avoid confusion.

## Detailed description¶

The following diagram shows the new proposed approach to slicing layers asynchronously.

As with the existing synchronous slicing design, the Dims.events.current_step event is the shared starting point. In the new approach, we pass ViewerModel.layers through to the newly defined LayerSlicer, which makes a slice request for each layer on the main thread. This request is processed asynchronously on a dedicated thread for slicing, while the main thread returns quickly to the Qt main event loop, allowing napari to keep responding to other updates and interactions. When all the layers have generated slice responses on the slicing thread, the slice_ready event is emitted. That triggers QtViewer.on_slice_ready to be executed on the main thread, so that the underlying QWidgets can be safely updated.

The rest of this section defines some new types to encapsulate state that is critical to slicing and some new methods that redefine the core logic of slicing.

### Request and response¶

First, we introduce a request to encapsulate the required input to slicing.

class LayerSliceRequest:
data: ArrayLike
world_to_data: Transform
point: Tuple[float, ...]
dims_displayed: Tuple[int, ...]
dims_not_displayed: Tuple[int, ...]

At a minimum, this request must contain the data to be sliced, the point at which we are slicing in napari’s shared world coordinate system, and a way to transform world coordinates to a layer’s data coordinate system. In the future, the point may become a bounding box that includes the current field of view. Given our understanding about the existing slice input state, each layer type should extend this request type to capture the input it needs for slicing, such as Points.face_color.

Second, we introduce a response to encapsulate the output of slicing.

class LayerSliceResponse:
data: ArrayLike
data_to_world: Transform

At a minimum, this response must contain the sliced data and a transform that tells us where that data lives in the currently displayed scene of napari’s shared world coordinate system. At this point data should be fast to access either from RAM (e.g. as a numpy array) or VRAM (e.g. as a CuPy array), so that it can be consumed on the main thread without blocking other operations for long.

For each layer type, we need to extend the request and response types to include state that is specific to slicing those types of layers. For example, the image request type should look something like the following.

class ImageSliceRequest(LayerSliceRequest):
rgb: bool
multiscale: bool
corner_pixels: np.ndarray
data_level: int

class ImageSliceResponse(LayerSliceResponse)
thumbnail: np.ndarray

As napari supports RGB and multi-scale images, we need a few more inputs to know what data should be accessed to generate the desired slice for the canvas. And the thumbnail needs to access the layer data as well, so should do so while we are slicing asynchronous to avoid any blocking behavior.

The points request and response types should look something like the following.

class PointsSliceRequest(LayerSliceRequest):
out_of_slice_display: bool
size: np.ndarray
shown: np.ndarray
face_color: np.ndarray
edge_color: np.ndarray
edge_width: np.ndarray

class PointsSliceResponse(LayerSliceResponse):
indices: np.ndarray
size: np.ndarray
view_size_scale: Union[int, np.ndarray]
face_color: np.ndarray
edge_color: np.ndarray
edge_width: np.ndarray

While the names and typing of some of the points request and response attributes are the same (e.g. face_color) they differ semantically because the response represent the sliced values only. Defining two distinct and explicit request and response types gives us more flexibility later in terms of how slicing works. For example, we may want to generate point face colors lazily, which could mean that PointsSliceRequest.face_color would become a callable instead of a materialized array as in the response.

### Layer methods¶

We require that each Layer type implements two methods related to slicing.

class Layer:
...

@abstractmethod
def _make_slice_request(dims: Dims) -> LayerSliceRequest:
raise NotImplementedError()

@abstractmethod
@staticmethod
def _get_slice(request: LayerSliceRequest) -> LayerSliceResponse:
raise NotImplementedError()

The first, _make_slice_request, combines the state of the layer with the current state of the viewer’s instance of Dims passed in as a parameter to create an immutable slice request that the slicing operation will use on another thread. This method should be called from the main thread, so that nothing else should be mutating the Layer or Dims. Therefore, we should try to ensure that this method returns quickly, so as not to block the main thread.

Most of the request’s fields, like point and dims_displayed are small, and can be quickly copied in this new instance. Other fields, like data, are too large to copy in general, so instead we store a reference. If that reference is mutated in-place on the main thread while slicing is being performed on another thread, this may create an inconsistent slice output depending on when the values in data are accessed, but should be safe because the shape and dtype cannot change. If Layer.data is reassigned on the main thread, then we can safely slice using the reference to the old data, though we may not want to consume the now stale output.

The second, _get_slice, takes the slice request and generates a response using layer-type specific logic. The method is static to prevent it from using any layer state directly and instead can only use the state in the immutable slice request. This allows us to execute this method on another thread without worrying about mutations to the layer that might occur on the main thread.

The main consumer of a layer slice response is the corresponding vispy layer. We require that a vispy layer type implement _set_slice to handle how it consumes the slice output.

class VispyBaseLayer:
...

@abstractmethod
def _set_slice(self, response: LayerSliceResponse) -> None:
raise NotImplementedError()

### Layer slicer¶

We define a dedicated class to handle execution of slicing tasks to avoid the associated state and logic leaking into the already complex ViewerModel.

ViewerSliceRequest = dict[Layer, LayerSliceRequest]
ViewerSliceResponse = dict[Layer, LayerSliceResponse]

class LayerSlicer:
...

def __init__(self, ...):

def slice_layers_async(self, layers: LayerList, dims: Dims) -> Future[ViewerSliceResponse]:
requests = {
layer: layer._make_slice_request(dims)
for layer in layers
}

def slice_layers(self, requests: ViewerSliceRequest) -> ViewerSliceResponse:
return {layer: layer._get_slice(request) for layer, request in requests.items()}

def _on_slice_done(self, task: Future[ViewerSliceResponse]) -> None:
return

For this class to be useful, there should be at least one connection to the slice_ready event. In napari, we expect the QtViewer to marshall the slice response that this signal carries to the vispy layers so that the canvas can be updated.

### Hooking up the viewer¶

Using Python’s standard library threads in the ViewerModel means that we have a portable way to perform asynchronous slicing in napari without an explicit dependency on Qt.

class ViewerModel:
...

dims: Dims
_slicer: LayerSlicer = LayerSlicer()

def __init__(self, ...):
...
self.dims.events.current_step.connect(self._slice_layers_async)

...

def _slice_layers_async(self) -> None:
self._slicer.slice_layers_async(self.layers, self.dims)

Initially we intend for each instance of ViewerModel to own a single instance of a LayerSlicer for the lifetime of that ViewerModel instance. That allows the LayerSlicer to coordinate slicing of any or all layers for a particular viewer instance, while allowing multiple viewer instances to slice independently.

The main response to the slice being ready occurs on the QtViewer because QtViewer.layer_to_visual provides a way to map from a layer to its corresponding vispy layer.

class QtViewer:
...

viewer: ViewerModel
layer_to_visual: Dict[Layer, VispyBaseLayer]

def __init__(self, ...):
...

for layer, response in responses.items():
if visual := self.layer_to_visual[layer]:
visual._set_slice(response)

The other reason is because QtViewer is a QObject that lives in the main thread, which makes it easier to ensure that the slice response is handled on the main thread. That’s useful because Qt widgets and vispy nodes can only be safely updated on the main thread 8, both of which occur when consuming slice output.

## Implementation¶

A tracking issue 9 serves as a way to communicate high level progress and discussion.

A prototype 10 has been created that implements the approach described above to show its basic technical feasibility in napari’s existing code base. It only implements it for some layer types, some slicing operations, and may not work when layer data is mutated. There are some other rough edges and plenty of ways to break it, but basic functionality should work.

The rough implementation plan is as follows.

• Implement pure refactors related to slicing to support this work (no public API or behavior changes).

• Implement high-level asynchronous slicing model described here (i.e. add LayerSlicer, changes to ViewerModel), but with existing layer slicing implementation (i.e. Layer._set_view_slice).

• Incrementally add layer slicing implementation described here (i.e. Layer._get_slice) for each layer separately.

This allows us to merge small pieces of work into main, testing and fixing them as we go. The alternative is to maintain a large branch/fork of napari that may be less tested and harder to merge in the end.

## Backward compatibility¶

### Breaks synchronous slicing behavior¶

The main goal of this project is to perform slicing asynchronously, so it’s natural that we might break anyone that was depending on slicing being synchronous. In particular, users or plugins that rely on Viewer.screenshot to capture the contents of the canvas after updating things like Dims.current_step will be affected.

Our proposal will break that usage in general, but we plan to offer some public way to force synchronous slicing. For example, one promising idea is to define a context manager that would temporarily force LayerSlicer to always wait for asynchronous tasks to finish and could be used as follows.

with viewer.sync_slicing():
viewer.dims.current_step = (10, 0, 0)
viewer.screenshot(...)

Having such a mechanism in LayerSlicer also allows us to implement support for async slicing incrementally for each layer type.

### Store existing slice state on layer¶

Many existing napari behaviors depend on the existing slice input and output state on the layer instances. In this proposal, we decide not to remove this state from the layer yet to prevent breaking other functionality that relies on it. As slice output is now generated asynchronously, we must ensure that this state is read and written atomically to mutually exclude the main and slicing thread from reading and writing inconsistent parts of that state.

In order to do this, we plan to encapsulate the input and output state of each state into private dataclasses. There are no API changes, but this forces any read/write access of this state to acquire an associated lock.

## Future work¶

### Render each slice as soon as it is ready¶

In this proposal, the slicing thread waits for slices of all layers to be ready before it emits the slice_ready event. There are a few reasons for that.

1. We only use one slicing thread to keep behavior simple and to avoid GIL contention.

2. It’s closer to the existing behavior of napari

3. Shouldn’t introduce any new potential bugs, such as 11.

4. It needs less UX design work to decide what should be shown while we are waiting for slices to be ready.

In some cases, rendering slices as soon as possible will provide a better user experience, especially when some layers are substantially slower than others. Therefore, this should be high priority future work.

To implement this behavior as a small extension to this proposal, we could do something like the following.

• Use multiple workers in the LayerSlicer._executor.

• Submit each call to Layer._get_slice separately.

• When each call is done, emit a separate slice_ready event that only contains each layer’s slice response, so that the viewer/vispy can update as soon as possible.

This would cause a more complex call sequence and could make cancellation behavior more complex, but may be worth it regardless.

## Alternatives¶

### Extend the existing experimental async code¶

• Already being used somewhat successfully by some napari users in the wild.

• Can still reuse some of the code, tooling, and learnings from this project.

• The technical design of this approach was not well received (i.e. there is a reason it is experimental).

• Does not address goal 2.

### Just call set_view_slice or refresh asynchronously¶

• Simple to implement with few code changes needed.

• Needs at least one lock to provide sensible access to layer slice state.

• This will need to be acquired to access this state and at the beginning of many methods that access any of that state.

• How to emit events on the main thread?

• Does not address goal 2.

### Just access data asynchronously¶

• Targets main cause of unresponsiveness (i.e. reading data).

• No events are emitted on the non-main thread.

• Less lazy when cancelling is possible (i.e. we do more work on the main thread before submitting the async task).

• Splits up slicing logic into pre/post data reading, making program flow harder to follow.

• Does not address goal 2.

### Use QThread and similar utilities instead of concurrent.futures¶

• Standard way for plugins to support long running operations.

• Can track progress and allow more opportunity for cancellation with yielded signal.

• Can easily process done callback (which might update Qt widgets) on main thread.

• Need to define our own task queue to achieve lazy slicing.

• Need to connect a QObject, which ties our core to Qt, unless the code that controls threads does not live in core.

### Use asyncio package instead of concurrent.futures¶

• May improve general readability of async code for some.

• Mostly syntactic sugar on top of concurrent.futures.

• Likely need an asyncio event loop distinct from Qt’s main event loop, which could be confusing and cause issues.

• As discussed on Zulip, qt-async-threads is a possible solution, but it is still quite new.

### Slice from vispy layer instead of viewer model¶

Instead of making the ViewerModel the driver of slicing, we could instead drive it from the vispy layers. A rough implementation of this approach could look like the following.

class QtViewer:
...
def __init__(self):
...
self.viewer.dims.current_step.connect(self.slice_layers)

def slice_layers(self):
for layer in self.viewer.layers:
self.layer_to_visual[layer]._slice(self.viewer.dims)

class Image:
...
def _make_slice_request(self, dims: Dims) -> ImageSliceRequest:
...
def _get_slice(self, request: ImageSliceRequest) -> ImageSliceResponse:
...

class VispyImageLayer:
...
def _slice(self, dims: Dims) -> None:
request = self.layer._make_slice_request(dims)

def _on_slice_done(self, task: Future[ImageSliceResponse]) -> None:

def _set_slice(self, response: ImageSliceResponse) -> None:
...

Most of the internal guts of slicing, such as the implementation of _get_slice and _make_slice_request, are unchanged from the approach proposed here.

The main advantage of this approach is that the main consumer of the slice response (i.e. vispy) is the one driving slicing, which allows us to better define input and output types and avoid unnecessary type inheritance.

In the example code above, we avoid a tight dependency on Qt using @ensure_main_thread. But another advantage of this general approach is that we could rely on tighter dependencies between vispy and Qt, which may simplify the implementation and offer some performance benefits.

One disadvantage is that it becomes harder to control the execution of multiple layers being sliced. For example, with the above implementation we can no longer wait for all layers to be sliced before updating all the vispy layers. Another disadvantage is that this implies that slice state should not live in the model in the future, which might cause issues with things like selection that may depend on that state.

## Discussion¶

• Consider (re)sampling instead of slicing as the name for the operation discussed here.

• Problems with NAPARI_ASYNC=1

• The existing experimental async code doesn’t handle some seemingly simple usage.

• Remove slice state from layer

• Feature request to remove slice/render state from the layer types.

• Motivated by creating multiple slices of the same layers for multiple canvases.

• Decision: postpone.

• There are too many behaviors that depend on slice state (e.g. Layer._get_value) and it’s easy enough to set it after an async slicing task is done, so leave it for now.

• This work should simplify removing it in the future.

• Draft PR on andy-sweet’s fork

• Initial feedback before sharing more widely.

• Define a class that encapsulates the slicing bounding box in world coordinates.

• Replace layer slice request and response types with a single slice type

• Motivation is make it easier to add a new layer type by reducing the number of class types needed.

• Some disagreement here as one type for two purposes (input vs. output) seems confusing.

• Keeping the request and response types separate may also allow us to better target alternatives to vispy.

• Decision: keep request and response types separate for now.

• Adding a new layer type is not a frequent occurrence.

• Having one class may reduce the number of classes, but implementing a new layer type is already quite complex.

• How to handle future cases where layer data has been pre-loaded onto the GPU and we want to slice in the shader?

• Less about large/slow data, and more about not blocking approaches to handling small/fast data efficiently.

• May be particularly useful for multi-canvas.

• Decision: postpone.

• Keep related types private or vague to not blocking this in the future.

• Support existing usage and plugins that depends on synchronous slicing

• Main example is the napari-animation plugin, but there may be others.

• This was explored 12 with the following main findings.

• Forcing synchronous slicing when combining the prototype and napari-animation seems to work for the basic examples.

• We only need to ensure synchronous slicing before using Viewer.screenshot, as keyframes just capture the value of current_step and similar.

• screenshot is only called a few times in napari-animation, so wouldn’t require large changes if asynchronous slicing was the default.

• Decision: always have some way to force synchronous slicing.

• But no need to support synchronous slicing by default, which is harder to implement.

• What should Viewer.screenshot do when the canvas is not fully rendered?

• Initial consensus is that it should wait for pending slicing tasks and for the associated pushes to vispy.

• There are some ideas of how to implement that, though it is not straightforward.

• In the API, may want a keyword argument to control behavior. In the GUI, could have a dialog if there are pending tasks. = Decision: want to support both, with blocking behavior as default.

• No need for a design or prototype before acceptance.

• Should Dims.current_step (and corner_pixels) represent the last slice position request or the last slice response?

• With sync slicing, there is no distinction.

• With async slicing, current is ambiguous.

• Initial small consensus around last request

• Decision: last request.

• The implementation is simpler if this represents the last request.

• Can introduce an additional public attribute later if last response is needed.

## References and footnotes¶

All NAPs should be declared as dedicated to the public domain with the CC0 license 13, as in Copyright, below, with attribution encouraged with CC0+BY 14.


text:
# A satellite moving in a circular path of radius r around earth has a time period T .if it's radius slightly increases by 4% then percentage change in its time period is

Arun
25763 Points
3 years ago
Dear student

According to Kepler's law-
T² = kr³
2T dT/dr = 3 k r² = 3 T²/r
dT/dr = 3/2 T/r..
Hence
dT = (3T/2r)* $\Delta$ r
Now put the value of $\Delta$r = 0.04 r and find answer
Regards

format: plain


text:
## LATEX-L@LISTSERV.UNI-HEIDELBERG.DE

 Options: Use Forum View Use Monospaced Font Show Text Part by Default Condense Mail Headers Message: [<< First] [< Prev] [Next >] [Last >>] Topic: [<< First] [< Prev] [Next >] [Last >>] Author: [<< First] [< Prev] [Next >] [Last >>]

```Hi all,

> it seems to me that this all boils down to "i want to ensure that all is
> Type1" so that i get proper pdf files. or am i wrong?

That could be a possible reason, but very likely some people could
find other reasons. But yes, that is what I was thinking about.
More generally, the automatic selection should be done taking
into account possible restrictions/features defined by the user.
(Which restrictions/features can be set is to be studied.)

It should be noted, however, that text also contains symbols and that
usually we are using _two_ encodings -- if we say \defaultencoding{T1},
\textdagger is taken from cmsy, which is the default symbol font (OMS).
So we have another problem when selecting an encoding -- in fact
we must select two.

Instead of multilingual documents, I would rather speak of multiscript
documents, since imo this concept is more important. Of course, different
languages use the latin script in different ways, but when there are
languages using diffent scripts there are additional problems. For
example, in a text containing both latin and cyrillic scripts the
following line of code might not make sense:

\usepackage{times}
\usepackage{textcomp}

Is times applied to both scripts? What happens if for some reason
I like cyrillic times and latin palatino? Which symbol fonts are used?
And if there is no times font for cyrillic? Or there is no symbol
font? If you use latin with tibetan, things are more complicated
because tibetan doesn't understand what a times font is, and again,
what happens if a certain script requires two or more metrics and/or
encodings?

Finally, it remains the problem of what happens if people dislike
the default settings. But that is unavoidable...

Javier
___________________________________________________________
Javier Bezos              | TeX y tipografia


text:
# Molecular structure of Boc-Aib-Phe-Aib-Met-$NH_2$.DMSO. A fragment of a biologically active enkephalin analog

Prasad, Venkataram BV and Sudha, Subrahmanyam T and Balaram, Padmanabhan (1983) Molecular structure of Boc-Aib-Phe-Aib-Met-$NH_2$.DMSO. A fragment of a biologically active enkephalin analog. In: Journal of the Chemical Society: Perkin Transactions 1: Organic and Bio-Organic Chemistry (2). pp. 417-421.

 Preview
PDF
full.pdf

The tetra peptide t- butyloxycarbonyl- a-aminoisobutyryl- a-aminoisobutyryl- L-phenylalanyl- L-methionyl amide crystallizes in the orthorhombic space group P21212, with a = 9.096, b = 18.067, c = 21.701 A and Z = 4. The crystals contain one molecule of dimethyl sulphoxide (DMSO) associated with each peptide. The structure has been solved by direct methods and refined to an R value of 0.103 for 2 672 observed reflections. The peptide adopts a distorted 31 helical structure stabilized by two intramolecular 4 $\rightarrow$ 1 hydrogen bonds between the Boc CO and Aib(1) CO groups and the NH groups of Phe(3) and Met(4), respectively. A long hydrogen bond (N 0 = 3.35 A) is also observed between Aib(2) CO and one of the terminal amide hydrogens. The DMSO molecule is strongly hydrogen bonded to the Aib(1) NH group. The solid-state conformation agrees well with proposals made on the basis of n.m.r. studies in solution.


text:
# Partial Differential Equation $U_t - (U_x)^2 = 0$

Please can anyone help me solving this problem?

$$\frac{\partial U}{\partial t} - \left(\frac{\partial U}{\partial x}\right)^2 = 0$$

where $$U=U(x,t)$$ with side condition as $$U(x,0)=\cos x$$.

The problem is given in the following article: A. Thess, D. Spirn, B. Jüttner, "Viscous Flow at Infinite Marangoni Number", Physical Review Letters 75(25), 1995. doi:10.1103/PhysRevLett.75.4614

## migrated from physics.stackexchange.comJun 12 at 8:10

This question came from our site for active researchers, academics and students of physics.

• Shouldn't Burgers' equation have $\partial^2 U/\partial x^2$ rather than $(\partial U/\partial x)^2$ ? – John Rennie Jun 12 at 6:37
• it's special case in it – Mohan Aditya Sabbineni Jun 12 at 6:38
• the problem is given in the physical review letters volume 75, Number 25 Viscous flow at infinite Marangoni Number. – Mohan Aditya Sabbineni Jun 12 at 6:39
• You've asked the same question twice now. – Mattos Jun 12 at 9:59
• This question got migrated from physics to mathematics, so it appeared twice in mathematics – Mohan Aditya Sabbineni Jun 12 at 10:02

The article cited in OP deals with the convection problem $$\partial_t \theta + v \partial_x \theta = 0$$, where $$v = -H\theta$$ is expressed in terms of the Hilbert transform $$H\theta$$ of $$\theta$$. While discussing this model, the authors make some statements on the alternative model (p. 4615, top of 2nd column)

$$v = -\partial_x\theta$$, which leads to the well-known Burgers equation $$\partial_t\theta - (\partial_x\theta)^2 = 0$$

This is actually an Hamilton-Jacobi equation, which classical resolution relies on the Lax-Hopf formula. A Burgers-like equation is recovered after differentiation of the above PDE with respect to $$x$$: $$g_t - 2 g g_x = 0, \qquad\text{with}\qquad g = \theta_x .$$ The solutions deduced from the method of characteristics satisfy the implicit equation $$g = -\sin (x +2g t)$$ of which no analytical solution is known. This classical solution is valid up to the breaking time $$t=1/2$$ when it breaks down, as displayed on the plot of the characteristics in $$x$$-$$t$$ plane below:

Along the characteristic lines, the variable $$g = -\sin(x_0)$$ is constant. Moreover, we have $$\frac{\text d}{\text d t} \theta = \theta_x \frac{\text d}{\text d t} x + \theta_t = -2g\theta_x + \theta_t = -g^2 ,$$ so that $$\theta = \cos(x_0) - g^2 t$$ along the characteristics. Thus, $$\theta = \cos(x +2g t) - g^2 t, \qquad\text{with}\qquad g = -\sin(x +2g t) .$$ Below is a Matlab script for this computation, along with its output (requires Optimization Toolbox):

nx = 200;
nt = 10;
tf = 0.49;
x = linspace(0,2*pi,nx);
t = linspace(0,tf,nt);
g = -sin(x);
theta = cos(x);

figure(1);
clf;
subplot(1,2,1);
hg = plot(x,g,'k-');
xlim([0 2*pi]);
ylim([-1 1]);
xlabel('x');
ylabel('g');
ht1 = title(strcat('t =',num2str(t(1))));
subplot(1,2,2);
htheta = plot(x(2:nx),theta(1,2:nx),'k-');
xlim([0 2*pi]);
ylim([-1 1]);
xlabel('x');
ylabel('\theta');
ht2 = title(strcat('t =',num2str(t(1))));

for i = 2:nt
fun = @(g) g + sin(x+2*g*t(i));
g = fsolve(fun,-((x<pi).*x+(x>pi).*(x-2*pi))/(1+2*t(i)));
theta = cos(x+2*g*t(i)) - g.^2*t(i);
set(hg,'YData',g);
set(htheta,'YData',theta(2:nx));
set(ht1,'String',strcat('t =',num2str(t(i))));
set(ht2,'String',strcat('t =',num2str(t(i))));
drawnow;
end

• I too proceeded in the same way and got the same result g= -sin(x+2gt) but can't we solve further to get thetha? – Mohan Aditya Sabbineni Jun 13 at 9:07
• In Matlab, I am facing this problem with the above code "Subscript indices must either be real positive integers or logicals." and thus unable to obtain the second plot. Please help me out – Mohan Aditya Sabbineni Jun 14 at 19:07

This equation can be solved by the method of characteristics. Let us start by changing variables, and use the field

$$v(x,t) = -2 \partial_x U(x,t) \, .$$

Indeed, in terms of $$v(x,t)$$, the problem is

$$\partial_t v + v \partial_x v= 0 \, , \qquad v(x,0) = f(x) = 2 \sin(x) \, . \qquad (*)$$

Then the solution of this differential equation comes from the observation that

$$\frac{d}{dt}v(z(t),t) = 0 \, , \qquad \text{if} \qquad \frac{dz}{dt} = v(z(t),t) = v_0 = f(z(0)) \, .$$

The right-hand-side of the second equation is a constant as a consequence of the first equation that tells us that $$v(z(t),t)$$ is a constant. Then if in order to compute $$v(x,t)$$, we need to find $$x_0$$ such that $$z(0) = x_0$$ and $$z(t) = x$$. I.e. solve

$$f(x_0) t + x_0 = x \, , \qquad \rightarrow \qquad x_0 = x_0(x,t) \, . \qquad (**)$$

In the case $$f(x) = 2 \sin(x)$$, this has to be done numerically for most choices of $$x$$ and $$t$$. Finally this solution can be inserted back into

$$v(x,t) = v(z(t),t) = v(z(0),0) = v(x_0(x,t),0) = f(x_0(x,t)) \, .$$

Modulo the numerical solution of ($$**$$), this answers the question.

Things get difficult (and interesting) when ($$**$$) can not be solved. With $$f(x) = 2 \sin(x)$$, this happens when $$t\geq 1/2$$ and ($$**$$) has multiple solutions. Then ($$*$$) can not be solved. It is however possible to circumvent this problem by coming up with a prescription to decide which solution to pick. With such a prescription, it turns out that that $$v(x,t)$$ jumps from one solution to another as $$x$$ is changed. $$v(x,t)$$ develops discontinuities for $$t>1/2$$ and displays so-called shocks. See e.g. wikipedia.

An intuitive (and physically based) prescription is to introduce a viscosity term

$$\partial_t v + v \partial_x v= \nu \partial_x^2 v \, , \qquad (***)$$

and define the solution of ($$*$$) as the solution of ($$***$$) in the limit $$\nu \rightarrow 0$$. As long as $$\nu >0$$, ($$***$$) has a smooth and well defined solution. This solution becomes however discontinuous in the desired limit $$\nu \rightarrow 0$$, and shocks emerge naturally. Moreover, in the absence of shocks, the limit $$\nu \rightarrow 0$$ can be taken straightforwardly and the solutions of limit of the solution of ($$*$$) coincides with the solution of ($$***$$).

I conclude with a short comment on terminology: To me (and also to wikipedia), ($$*$$) is Burgers' equation and $$\partial_t U - [\partial_x U]^2=0$$ is the KPZ equation without viscosity and noise. These two names are often mixed up because both equations are equivalent as I show in the beginning of my answer.

I quickly wrote a short Mathematica code to solve the above equation up to $$t=1/2$$:

X0[x_, t_] := x0 /. FindRoot[2 Sin[x0] t + x0 == x, {x0, x}]
v[x_, t_] := 2 Sin[X0[x, t]]
U[x_, t_, Npts_] := -1/2 Sum[v[x (i - 1)/(Npts - 1), t] x/(Npts - 1), {i, 1, Npts}] + 1

The first line solves ($$**$$), the second line computes $$v(x,t)$$ and the third line converts it back to $$U(x,t)$$ with the correct initial conditions. I implemented the integration over $$v(x,t)$$ as a Rieman sum with $$Npts$$ the number of discrete elements. With $$Npts=50$$, I get the following plot:

The vertical axis represents $$U$$, the horizontal axis (from $$2\pi$$ to $$0$$) is $$x$$ and the 'depth' axis (from $$0$$ to $$1/2$$) is $$t$$. The plot is generated in Mathematica with

Plot3D[U[x, t, 50], {x, 0, 2 Pi}, {t, 0, 1/2}]

The formation of a shock at $$x=\pi$$ and $$t=1/2$$ is visible here as a kink in $$U(x,t)$$. Remember that $$v = -2 \partial_x U$$, so that a kink in $$U$$ is equivalent to a jump in $$v$$.


text:
## Gentler wakeups with Home Assistant 🥱

##### wakemeup.py
HowTos homeassistant snapcast appdaemon homeautomation iot

Ever watched a movie set in the future, where the protagonist wakes up and the blinds in the room go up, the music starts gently and coffee is automatically served?

Well, the future is now!

This guide goes through how you can trigger this using any alarm application on Android via Tasker, so no additional app (except Tasker which runs in the background), or other hassle to deal with!

# Home Assistant

The movies set in the future always used HomeAssistant, didn’t you know? And for good reason! Because when you have your blinds, lights, coffeemaker, etc, the effort to implement them into HomeAssistant is extremely effortless. And when that’s done, there is no stopping you from automating it all to your hearts content.

This guide assumes that you already have stuff working in Homeassistant which you want to automate. If not, feel free to look at the following for inspiration:

## AppDaemon

To perform the automation on the Homeassistant side of things I’ve used Appdaemon. The advantage of Appdaemon is that it allows you to create more advanced automations using Python.

Installing Appdaemon itself is out of scope for this page, and is better explained by the author here: https://appdaemon.readthedocs.io/en/latest/INSTALL.html

In my case, the following script is used to wait for the alarm to be set for the next day, and add timers to trigger happenings based on it.

### Configuration

If you read through the script, you’ll see that it’s very much custom tailored towards me, and you will need to make many changes to make it match your need. Currently my version performs the following:

• When the alarm is set, fade down the lights in the room until 10%
• After 25s (LIGHTS_OFF_AFTER_ALARM_SET), turn the lights off
• One hour (TIME_BEFORE_ALARM) before the alarm goes off, start turning the lights on gently
• 20 minutes (RADIOTIME_BEFORE_ALARM) before the alarm goes off, turn on the radio at a low volume
• 30 seconds after the alarm has gone off, start brewing coffee (COFFEETIME_AFTER_ALARM)

Take it more as a inspirational template, than a finished product. Look through it, and change the Id’s, services and timings as you need. The Appdaemon documentation will probably come in handy.

### Installation

To install the script, simply copy it over to the apps directory of appdaemon. In my setup this is under ~/.appdaemon/apps. In addition to the script, you need a YAML configuration file in the same directory, something similar to this:

wakemeup:
module: wakemeup
class: WakeMeUp

The directory will then look similar to this:

~/.appdaemon/apps\$ ls
__pycache__  wakemeup.py  wakemeup.yaml

On the Android side of things we use Tasker and the AutoAlarm plugin to monitor set alarms and ship them over to Homeassistant.

## Configure

First we need to configure a task to help Tasker with calling the HomeAssistant API. To make things easier, I’ve provided a XML dump of the task here: CallHASS.tsk.xml

### Variables

Next up we need to set some variables for the task.

Then, if we want to make a button/widget to transmit the currently set alarm to HomeAssistant we can do so as this:

(again, to make things easier, I have a XML you may import to Tasker here: Set_alarm.tsk.xml )

If the XML import above failed you, this is how the “2. Perform task” in the previous screenshot was configured.

If you imported the Task from the XML (or created it correctly manually), you should now be able to run it by pressing the play-button. This should then result in you now getting a “Sleep Alarm” sensor in Home Assistant which denotes when your next alarm is set for.

Press the following button to get redirected to your entities list.

## Sleep As Android

To automatically trigger tasker to send the alarm time to HomeAssistant I’ve coupled the task with a trigger from “Sleep As Android”. Note, this app is not necessary, you may also trigger Tasker in other means (eg. on a timer, or with other apps if they support it).

To configure this I made a Profile in Tasker where the “Set Alarm Task” is ran each time I start the sleep-tracking in “Sleep As Android”.

# Conclusion

Congrats, you now live in the future too!

This post became somewhat messy and lacking in explanation in various parts, as due to all the different software components involved it’s hard to explain them all in the same detail.

If you got stuck then this post is also available on the Home Assistant forum here: automating-wakeups-with-tasker, feel free to poke me there to add some additional words where you feel it’s lacking.

Otherwise, La vita è bella, and thank you for being here :)


text:
# Since incidence rate ratios are always positive, how does one determine the sign of the effect?

I want the results from a Poisson regression to be comparable to previous OLS and Tobit regressions. To do this, I am utilizing the irr (incidence rate ratio) option in Stata. However, since all the estimated coefficients are being exponentiated, all irr coefficients are positive. Given that, how does one determine the sign of each estimated coefficient? Would it be kosher to just assume that the negative or positive sign from running the same Poisson estimation without the irr option is still applicable?

With linear regression and Tobit (assuming you are looking at the latent variable) the coefficients measure the difference in expected (latent) outocome for two groups who are one unit of your explanatory variable appart. So a positive sign for that coefficient means that the expected outcome increases with your explanatory variable and a negative sign means that your expected outcome decreases with your explanatory variable.

With models using a log-link function (e.g. poisson regression) the exponentiated coefficients measure the ratio of expected outcomes for two groups who are one unit of your explanatory variable appart. So a ratio larger than 1 means that the expected outcome increases with your explanatory variable and a ratio less than 1 means that the expected outcome decreases with your explanatory variable.

So if you want to know the "sign" of an incidence risk ratio you look at whether it is larger or smaller than 1. This is equivalent to looking at whether the raw coefficients are larger or smaller than 0 ($\exp(0)=1$).


text:
# Software tutorial/Dealing with factors (categorical variables)

This section shows a bit about R's ability to deal with factors. Factors are variables that are coded for categories: e.g. male and female, or another example could be day of the week: Monday, Tuesday, ..., Sunday.
When you loaded the website data, not all of the raw data (take a look inside the CSV file) is numeric. The DayOfWeek is text, so R assumes this is a factor. It automatically goes and finds all unique values in that column (the names of the 7 days in the week in this case), and codes that as factor variable. But it sorts them alphabetically, Friday, Monday, ..., Wednesday. If you want them in a different order, use the levels input option to tell R your preferred order:
day.names <- c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" )
days <- factor(website$DayOfWeek, level=day.names) boxplot(website$Visits ~ days)

Now that boxplot will be ordered in a more useful way to see the weekly trends. The c() command creates a combination of items and the factor() command creates a factor variable.


text:
# zbMATH — the first resource for mathematics

On the parity of ranks of Selmer groups. II. (English. Abridged French version) Zbl 1090.11037
Let $$E/\mathbb Q$$ be an elliptic curve with conductor $$N$$ and let $$p$$ be a prime number. For each number field $$F$$ and integer $$m\geq 1$$, let $$S(E/F,m)$$ be the Selmer group of $$E/F$$ relative to $$m$$. We have an exact sequence
$0\to E(F)\otimes\mathbb Q_p/\mathbb Z_p\to S_p(E/F)\to\text Ш(E/F)[p^{\infty}]\to 0,$
where $$S_p(E/F)=\varinjlim_nS(E/F,p^n)$$. The main result of the paper states that if $$E$$ has good reduction at $$p$$, then $$\text{corank}_{\mathbb{Z}_p}S_p(E/\mathbb{Q})\equiv\text{ord}_{s=1}L(E,s)\pmod 2$$, where $$L(E,s)$$ denotes the Hasse-Weil $$L$$-function of $$E$$. This result can be obtained as a weak consequence of the Birch and Swinnerton-Dyer conjecture and is known as the parity conjecture for Selmer groups. The result is deduced from the following theorem.
Let $$K$$ be an imaginary quadratic field, suppose the prime factors of $$N$$ are decomposed in $$K/\mathbb Q$$. If $$E$$ has good reduction at $$p$$, then $$\text{corank}_{\mathbb Z_p}S_p(E/K)\equiv 1\pmod 2$$.
The reader can find references for earlier results in Part I [the author and A. Plater, Asian J. Math. 4, No. 2, 437–497 (2000; Zbl 0973.11066)].

##### MSC:
 11G40 $$L$$-functions of varieties over global fields; Birch-Swinnerton-Dyer conjecture 11G05 Elliptic curves over global fields 11F33 Congruences for modular and $$p$$-adic modular forms 11F66 Langlands $$L$$-functions; one variable Dirichlet series and functional equations
##### Keywords:
Selmer groups; elliptic curve; parity conjecture
Full Text:


text:
# IMAT 2019 Q58 [Equation]

In order to solve this, we will multiply the whole equation with x(x-2). This is possible because neither of them are 0.

We get:
3(x-2) + 2x = x(x-2) \to 3x-6+2x = x^2 -2x \to x^2 -2x -5x +6 =0 \to x^2 -7x +6 =0

We can now either use the formula for x_{1,2} or solve it like this:
x^2 -7x +6 = x^2 -x -6x +6 = x(x-1) -6 (x-1) = (x-1)(x-6) \to (x-1)(x-6) = 0 \to x_1 = 1, x_2 = 6

Adding those together we get the final solution:
x_1 +x_2 = 1+6 = 7 (E)

1 Like


text:
# SI

• August 12th 2009, 10:06 AM
bluffmaster.roy.007
SI
A person spends a part of amount of $20,000 for buying. 40% of the remaining amount is given at 6% interest and the rest money is given at 10% interest. If the total interest the person gets is$1250, then what is the amount he used for buying?
• August 12th 2009, 11:29 AM
Wilmer
I do not understand what you posted.
• August 12th 2009, 12:14 PM
e^(i*pi)
Quote:

Originally Posted by bluffmaster.roy.007
A person spends a part of amount of $20,000 for buying. 40% of the remaining amount is given at 6% interest and the rest money is given at 10% interest. If the total interest the person gets is$1250, then what is the amount he used for buying?

Quote:

Originally Posted by Wilmer
I do not understand what you posted.

My Interpretation

1. A person gets $20,000 2. This person then spends an amount of money 3. 40% of the remainder attracts 6% interest 4. 10% of the remainder (from step 2) attracts 10% interest. ---------- Let x be the amount he spends and y be the amount which gets interest $y = 20,000-x$ 40% of y gets 6% interest: $0.4y(1.06)^n$ 60% of y gets 10% interest: $0.6y(1.10)^n$ 0.4y(1.06)^n + 0.6y(1.10)^n = 1250 If we assume n is over one period of time (usually annually) so that will cancel $0.424y+0.66y = 1250$ $1.084y = 1250$ $ y = 1153.1365$ $x = 20000-y = 20000-1153.1365 = \18846.86$ • August 12th 2009, 06:49 PM Soroban Hello, bluffmaster.roy.007! I interpreted it differently . . . Quote: A person spends a part of amount of$20,000 for buying.
40% of the remaining amount is given at 6% interest
and the rest of the money is given at 10% interest.

If the total interest the person gets is $1250, then what is the amount he used for buying? The person has$20,000.
He spend $x$ dollars for buying.
He has $20,\!000-x$ dollars remaining.

40% of this remainder is: . $0.40(20,\!000-x)$ dollars.
This earns 6% interest: . $I_1 \:=\:(0.06)(0.40)(20,\!000-x)\:=\:480 - 0.024x$

60% of the remainder is: . $0.60(20,\!000-x)$ dollars.
This earns 10% interest: . $I_2 \:=\:(0.10)(0.60)(20,\!000-x) \:=\:1200 - 0.06x$

The total interest is $1250: . $(480-0.024x) + (1200 - 0.06x) \:=\:1250$ We have: . $0.084x \:=\:430 \quad\Rightarrow\quad x \:=\:\frac{430}{0.084} \:=\:5119.047619$ Therefore, he used$5,119.05 for buying.

• August 18th 2009, 01:46 PM
mobyn3d
alternate solution......
Mr sorobon is rite..........
lets see how eazy it is..........consider x be the amount remainin...
that is x=20,000-amount used for buying.

40% of remaining amount x gets 6%interest
that is......(0.4)(0.06)(x)

and for second interest (0.6)(0.1)(x)

together they make 1250$=0.024x+0.06x x=1250/0.084=14880.1 so amount used for buying is 20,000-x and that is 5119.9$....


text:
# Are there “Introductory flights” available to see if I want to pursue training?

Through endless sources available it's possible to learn the rules of flying without undertaking formal training: I can take practice tests, study flying rules, laws, altitudes, speeds, controls, etc., however, I'd like to try out actually flying (preferably for free) before considering the option of paying for a full license.

Basically I'd like to take a trial flight - I don't care if someone has to sit with me, but I'm not keen on the idea of spending a lot of money before at least having one flight under my belt.

Teens often drive before getting licensed in private; any options for me to do the same with aircraft machines?

-
Teens might drive before paying anything, but the drive is not free.... someone has to pay for the car, and the gas and maintenance, unless something definitely illegal is going on! If the $100 or so it costs to take a discovery flight is beyond your impulse budget (meaning it's enough that you would not be comfortable spending it), flying lessons simply are not for you until your financial situation changes. This is a rewarding hobby but not an inexpensive one, and if you're curious for the career aspect, understand it takes a long time to pay back your learning costs. – mah Mar 4 at 0:36 Teens driving around before they get their license need to have access to a car -- Either one their family owns ("free"), or one provided by a driving school ($). A similar situation exists with aircraft: Either you know someone with a plane, or you get access to one through a flight school... –  voretaq7 Mar 4 at 4:31

Well, to put it bluntly, somebody has to pay for the airplane. Much like a car, somebody has to pay for the gas and maintenance. The major difference is that both cost a lot more on an airplane so it is a lot harder to get someone else to pay for it.

However, similar to a car, if you have a friend that owns an airplane they may take you up for a ride and even (legally) let you fly it, but they remain the person in charge and responsible for the safe outcome of the flight. If you want to try it for free this is probably one of the only ways to do it.

If you are willing to pay for a one-time flight which does not commit you to pay for your entire license, then you can go to most any place that teaches people how to fly and they will be happy to let you fly with an instructor and charge you only for the time in the airplane and the time with the instructor. Often they have an "introductory" flight just for this purpose which is discounted for potential students. This is a relatively small cost in comparison to learning to fly that I highly recommend to anyone before they commit to getting their license.

-

Very many if not all flight schools offer a scenic/tour/experience/introductory flight in a general aviation aircraft such as a Cessna for the specific purpose of knowing if you want to seriously pick up flying, but I doubt you can convince you to do it for free- possibly they might give it as a discount when you sign up for a full course.

Otherwise there are many facilities nowadays which offer to test a full-scale simulator. Here again, it will cost a bit but you'll probably be a good deal of fun.

The 'problem' is that aircraft are prohibitively expensive to ride on for free- you're often looking at 100$+ an hour with an instructor, who you can't go without. In europe, there's a good chance you're looking at 150€ or so for the same, but these are just estimates. It's an awfully lot more expensive than cars. But if you're serious about spending several thousand dollars for a license, it won't hurt to get up a little before you commit yourself fully, and even paying the cost of a flight will be tiny if insignificant in regards to the future training cost. Information Online I certainly agree with you that there's a lot of information online, but it doesn't substitute learning to understand the aircraft, and there's no substitute to the real world. The FAA says you need at least 40 hours of flying, along with a list of other requirements to get your license. - As has been pointed out, most flight schools aren't going to take you up "for free" -- at a bare minimum they need to recoup the cost of fuel (right now somewhere between US\$50-70 for an hour in the air) and pay the instructor that goes up with you (flight instructors have this odd desire to eat food occasionally).

This usually boils down to about US\$100 to \$150 for a "discovery flight" (and at that price the school is often taking a small loss with the hope that you'll come back and train with them). It will probably be your cheapest flight lesson.

All is not lost however! There is one reasonably viable option to get a free flight: Meet a pilot and ask if you can tag along on their next trip.

You don't say where you're located, but most general aviation airports have a pilot's association or flying club. Visit your local airport and find out when they meet, show up, and introduce yourself. If local pilots know you're interested in flying the good ones will usually go out out of their way to keep you interested, and if you're not sure about committing the time and money to obtain a license a trip with a local pilot where you actually go somewhere is a great introduction (arguably better than the typical "discovery flight" where you go up, do some maneuvers, and go back to the airport you started at).

-

I remember I got a free hour from American Flyers when I told them I was thinking about switching to them in the middle of my instrument rating training. Not sure if they do that for intro flights as well.

-


text:
## Proceedings of the Centre for Mathematics and its Applications

### Non-reflexive realizations of non-distributive subspace lattices

W. E. Longstaff

#### Abstract

Let $F$ be a subspace lattice on a (complex) Hilbert space H . A subspace lattice $F$ on a Hilbert space K is a realization of $F$ on K if $G$ is lattice-isomorphic to $F$. In 1975 it was proved that if $F$ is completely distributive every realization $G$ of it is reflexive (that is, $F$ is the set of invariant subspaces of a family of operators). A partial converse has recently been found: If every realization of $F$ is reflexive and $F$ has a finite--dimensional realization, then $F$ is completely distributive. This is proved by showing that every non-distributive subspace lattice on a finite-dimensional space has a non-reflexive realization on the same space.

#### Article information

Dates
First available in Project Euclid: 18 November 2014


text:
# zbMATH — the first resource for mathematics

Selfextensions de modules de Harish-Chandra et une question de I. M. Gelfand. (French) Zbl 0559.17007
Homologie, groupes Ext$$^ n$$ représentations de longueur finie des groupes de Lie, Astérisque 124/125, 31-48 (1985).
[For the entire collection see Zbl 0547.00015.]
Let G be a semisimple group, and X an irreducible Harish-Chandra module for G. This paper is concerned with the possible self-extensions of X. It is shown that they are in some sense controlled by the self-extensions of a one-dimensional module over a nice commutative algebra (usually a polynomial algebra). For X a generic principal series for a complex group, this control is made into an explicit equivalence of categories, verifying a conjecture of Gelfand.
Reviewer: D.Vogan

##### MSC:
 17B55 Homological methods in Lie (super)algebras 22E47 Representations of Lie and real algebraic groups: algebraic methods (Verma modules, etc.)


text:
### Author Topic: HA4-P3  (Read 1672 times)

#### Victor Ivrii

• Elder Member
• Posts: 1332
• Karma: 0
##### HA4-P3
« on: October 10, 2015, 07:24:04 AM »
« Last Edit: October 17, 2015, 05:28:35 AM by Victor Ivrii »

#### Bruce Wu

• APM346
• Sr. Member
• Posts: 57
• Karma: 0
##### Re: HA4-P3
« Reply #1 on: October 15, 2015, 12:41:21 AM »
Below is what I have so far. Please let me know if I am correct before I continue.
a) If $v>c$, then $x>ct$. In this region both $\phi(x+ct)$ and $\psi(x-ct)$ are fully defined. We do not need any boundary conditions, which is condition 1.
If $-c<v<c$, then $-ct<x<ct$. Here $\phi$ is fully defined but we need to define $\psi$ for negative arguments. Therefore we need 1 boundary condition, either 2. or 3. (need to work out which one)
If $v<-c$, then $x<-ct$. We need to define both $\phi$ and $\psi$ for negative arguments. We need 2 boundary conditions, so condition 4.

#### Victor Ivrii

• Elder Member
• Posts: 1332
• Karma: 0
##### Re: HA4-P3
« Reply #2 on: October 15, 2015, 01:57:32 AM »
Right

#### Zaihao Zhou

• APM346
• Full Member
• Posts: 29
• Karma: 0
##### Re: HA4-P3
« Reply #3 on: October 15, 2015, 11:32:58 AM »
Sorry I'm confused about what form of boundary conditions should take.

Why do we need here condition Ux=vt but not Ux=0? If x = vt means "location of the wave is its velocity times t" then why don't we use Ux=ct boundary condition for cases without v mentioned? Shouldn't c be the velocity? If we have v, what is c?

Could someone or professor please explain? Thanks!

#### Victor Ivrii

• Elder Member
• Posts: 1332
• Karma: 0
##### Re: HA4-P3
« Reply #4 on: October 15, 2015, 11:57:23 AM »
Fei Fan Wu provided almost full explanations. Solution is given by $u=\phi(x+ct)+\psi(x-ct)$ and initial data provide us with $\phi(x)$ and $\psi(x)$ as $x>0$. So $\phi(x+ct)$ is defined as $x+ct>0$ and $\psi(x-ct)$ is defined as $x-ct>0$.

a) $v>c$. Then $x+ct > x-ct >0$ as $x>vt$ ($t>0$).  completely defined!

b) $c>v> -c$.  Then $x+ct$ as $x>vt$ but $x-ct$ could be less than $0$ so we need to find $\psi(x)$ for negative $x$. For this we need 1 boundary condition. Plug $u$ to it:

(\alpha + \beta c) \phi' ((v+c)t) + (\alpha - \beta c )\psi' ((v-c)t) =0,\qquad t>0.

We can always find $\psi$ out of it except one special case which should be a mentioned.

c) $v<-c$. Then both $x-ct$ and $x+ct$ could be negative and we need to find $\phi(x)$ and $\psi(x)$ as $x<0$. We need two boundary conditions. Plug $u$ into boundary conditions:
\begin{align}
&\phi((v+c)t) + \phi'(v-c)t)=0,\\
c\phi '( (v+c)t)-c\psi'((v-c)t)=0. \end{align} Integrating the second one (never mind, constantC$could be safely taken$0$) and comparing with the first one we find that$\phi(x)=\psi(x)=0$as$x<0$. QED #### Zaihao Zhou • APM346 • Full Member • Posts: 29 • Karma: 0 ##### Re: HA4-P3 « Reply #5 on: October 15, 2015, 12:13:24 PM » Fei Fan Wu provided almost full explanations. Solution is given by$u=\phi(x+ct)+\psi(x-ct)$and initial data provide us with$\phi(x)$and$\psi(x)$as$x>0$. So$\phi(x+ct)$is defined as$x+ct>0$and$\psi(x-ct)$is defined as$x-ct>0$. a)$v>c$. Then$x+ct > x-ct >0$as$x>vt$($t>0$). completely defined! b)$c>v> -c$. Then$x+ct$as$x>vt$but$x-ct$could be less than$0$so we need to find$\psi(x)$for negative$x$. For this we need 1 boundary condition. Plug$u$to it: (\alpha + \beta c) \phi' ((v+c)t) + (\alpha - \beta c )\psi' ((v-c)t) =0,\qquad t>0. We can always find$\psi$out of it except one special case which should be a mentioned. c)$v<-c$. Then both$x-ct$and$x+ct$could be negative and we need to find$\phi(x)$and$\psi(x)$as$x<0$. We need two boundary conditions. Plug$uinto boundary conditions: \begin{align} &\phi((v+c)t) + \phi'(v-c)t)=0,\\c\phi '( (v+c)t)-c\psi'((v-c)t)=0.
\end{align}
Integrating the second one (never mind, constant $C$ could be safely taken $0$) and comparing with the first one we find that $\phi(x)=\psi(x)=0$ as $x<0$.

QED

Thanks professor but I understand the process of doing this but not why we need initial condition Ux=vt here but not Ux=0, or similarly when with problems without v, why not use boundary condition Ux=ct?

#### Victor Ivrii

• Elder Member
• Posts: 1332
• Karma: 0
##### Re: HA4-P3
« Reply #6 on: October 15, 2015, 01:05:40 PM »
Thanks professor but I understand the process of doing this but not why we need initial condition Ux=vt here but not Ux=0, or similarly when with problems without v, why not use boundary condition Ux=ct?

This is completely incomprehensible. What do you really mean by this charade?

#### Zaihao Zhou

• APM346
• Full Member
• Posts: 29
• Karma: 0
##### Re: HA4-P3
« Reply #7 on: October 15, 2015, 05:31:07 PM »
Thanks professor but I understand the process of doing this but not why we need initial condition Ux=vt here but not Ux=0, or similarly when with problems without v, why not use boundary condition Ux=ct?

This is completely incomprehensible. What do you really mean by this charade?
My questions is about boundary condition. For the general form of 1D wave, there is no v present. We used boundary condition$$u_{x=0} = 0$$. Here you are asking v. I understand that we need conditions, but why here we need:$$u_{x=vt} = something$$ but not $$u_{x=ct} = something$$ or $$u_{x=0} = something$$

And what is v? where does it come from and how it relates to c here?

Hope that clarifies my questions. Sorry for the confusion.

#### Emily Deibert

• APM346
• Elder Member
• Posts: 100
• Karma: 0
##### Re: HA4-P3
« Reply #8 on: October 15, 2015, 05:45:27 PM »
From my understanding v is just some constant that could have any value. We consider what conditions will be necessary for the various cases of v in relation to c (as mentioned in the problem).

#### Victor Ivrii

The domain is $\{t>0, x>vt\}$ and the b.c. is on its border, not inside!
This problem could be interpreted in the following way: we have an air pipe but its left end is moving with a constant speed $v$. If this movement is subsonic $|v|<c$ then there should be one condition on it, if the movement is supersonic $|v|>c$ then there should be either $2$ conditions as this end goes to the left or none as it goes to the right. It is a toy-model for 3D or 2D theory where we consider airflow which has different speeds at different points and the most difficult case is transonic when at some points it is subsonic but in others supersonic.


text:
# What exactly is the geodesic flow?

I understand what a geodesic is, but I'm struggling to understand the meaning of the geodesic flow (as defined e.g. by Do Carmo, Riemannian Geometry, page 63).

I can state my confusion in two different ways:

# 1)

Do Carmo writes:

Why does a geodesic $\gamma$ uniquely define a vector field on an open subset? In other words, why are the values of the vector fields uniquely defined on those points that are not on the geodesic $\gamma$?

# 2)

In local coordinates, the geodesic flow is defined as the solution to the ordinary differential equation

$$\tag{1}\frac{d^2 x_k}{dt^2}+\sum_{i,j}\Gamma^k_{ij}\frac{dx_i}{dt}\frac{dx_j}{dt}=0$$

For the solution to be unique on $TM$ (or on an open subset), we need some boundary condition. The only boundary condition I can see is a given geodesic $\gamma(t)$.

What are the boundary conditions for this ODE?

The basic idea behind the approach Do Carmo takes is to interpret a curve $(\gamma(t), \gamma'(t))$ where $\gamma \colon [a,b] \rightarrow M$ is a geodesic in $M$ as an integral curve of a globally defined vector field $G$ on $TM$. Once you do that, in order to show the existence of a geodesic $\gamma$ with $\gamma(0) = p$ and $\gamma'(0) = v$ (with $v \in T_pM$) you can take an integral curve $\beta \colon (a,b) \rightarrow TM$ of $G$ with $\beta(0) = (p,v)$ and then the projection $\gamma := \pi \circ \beta$ of $\beta$ to $M$ will be a geodesic which satisfies the initial conditions $\gamma(0) = p$ and $\gamma'(0) = v$.
The uniqueness of geodesics will follow from the uniqueness of integral curves of the vector field $G$, once a starting point $(p,v) \in TM$ is specified. There is no need to impose boundary conditions (and in general, an ODE with boundary conditions might have no solutions satisfying arbitrary boundary conditions), only initial conditions.
• Thank you, but I'm still at the same problem. Yes, the geodesic defines the vector field on the image of the geodesic, i.e. on the points $p$ that are on the geodesic. But take a point $\bar p$ which is not on the geodesic. How is the vector field at $\bar p$ defined? – Andy Miles Mar 20 '17 at 21:22
• @AndyMiles: It's not that a specific geodesic defines the vector field on the image of the geodesic, it's the geodesic equation which defines a vector field on $TM$ according to the formula given in Do Carmo. – levap Mar 20 '17 at 21:28
• Getting more confused. Are we talking about one vector field for all geodesics, or one vector field for each geodesic? In other words, does Do Carmo's lemma say "for each given geodesic $\gamma$, there is a unique vector field such that...", or does it say "there is one unique vector field such that for each geodesic $\gamma$ ..."? Is it $\forall\gamma\exists G$ or $\exists G\forall\gamma$? – Andy Miles Mar 20 '17 at 21:31
• @AndyMiles: The point is that there is one vector field whose integrals curves gives you all the geodesics. If you prefer to think about it in another way, assume first that all geodesics exist for a short time. For each $(p,v) \in TM$, consider a geodesic $\gamma(t)$ with $\gamma(0) = p$ and $\gamma'(0) = v$. Then $\beta(t) = (\gamma(t), \gamma'(t))$ is a curve in $TM$ and you want to find a vector field $G$ which is globally defined on $TM$ such that $\beta$ is an integral curve of $G$. – levap Mar 20 '17 at 21:36
• Thank you! Such a vector field seems better suited to accommodate for all geodesics than just a vector field on $M$ :-) – Andy Miles Mar 20 '17 at 21:44