3. Space & form#

3.1. Space#

Having abstract meshes, you can define abstract finite dimensional function spaces on them. To do so, we first need to set the target mesh by calling

>>> ph.space.set_mesh(mesh)

Note that if there is only one mesh defined, above command can be omitted.

Then, to define a finite dimensional function space on this mesh, call function ph.space.new,

new(abbr, *args, mesh=None, **kwargs)[source]#

Generate a spaces on the mesh.

Parameters:
abbrstr

The abbr. of the space.

args

The arguments to be sent to the space.

mesh{Mesh, None}, optional

We want to generate space on this mesh. If it is None, we use the current target mesh. The default value is None.

kwargs

The keyword arguments to be sent to the space.

Returns:
space

The finite dimensional space.

So far, we have implemented the following spaces.

Implemented spaces

description

abbr.

arg

kwarg

scalar-valued form space

'Lambda'

k : int. It is a \(k\)-form space.

orientation: {'inner', 'outer'}. The orientation of the form space. The default orientation is 'outer'.

For example, to make spaces of outer orientated 1-forms and 2-forms, do

>>> Out1 = ph.space.new('Lambda', 1, orientation='outer')
>>> Out2 = ph.space.new('Lambda', 2, orientation='outer')

And we can list all existing spaces by calling ph.list_spaces method,

>>> ph.list_spaces()  
Implemented spaces:...

Each space is an instance of a particular space class which inherits SpaceBase.

class SpaceBase(mesh, orientation)[source]#
make_form(sym_repr, lin_repr, dual_representation=False)[source]#

Define a form which is an element of this space.

Parameters:
sym_reprstr

The symbolic representation of the form.

lin_reprstr

The linguistic representation of the form.

dual_representationbool, optional

Whether the output form uses dual representation? The default value is False.

Returns:
formsrc.form.main.Form

The output form.

property manifold#

The manifold I am built on.

property mesh#

The mesh I am built on.

3.2. Form#

A form is simply an element of a space. Thus, it is logical to define a form through a space. To do that, just call the make_form method of the space instance (see src.spaces.base.SpaceBase.make_form()). The following code makes an outer oriented 2-form, a, in space Out2 and an outer-oriented 1-form, b, in space Out1.

>>> a = Out2.make_form(r'\tilde{\alpha}', 'variable1')
>>> b = Out1.make_form(r'\tilde{\beta}', 'variable2')

The arguments are their symbolic representations (r'\tilde{\alpha}', r'\tilde{\beta}') and linguistic representations ('variable1', 'variable2'), represectively. To list all defined forms, do

>>> ph.list_forms()
<Figure size ...

If you have turned off the py cache , see Set, a figure should have popped out. Otherwise, it is saved to ./__phcache__/Pr_current/. A form is an instance of Form.

class Form(space, sym_repr, lin_repr, is_root, update_cache=True)[source]#

The form class.

codifferential()[source]#

The codifferential, \(\mathrm{d}^\ast\), of this form.

cross_product(other)[source]#

The cross product, \(\times\), between this form and another form.

property degree#

This form is in the space of particular finite dimensional degree.

exterior_derivative()[source]#

The exterior derivative, \(\mathrm{d}\), of this form.

property manifold#

The manifold this form is on.

property mesh#

The mesh this form is on.

property orientation#

My orientation.

property space#

The space this form is in.

time_derivative(degree=1)[source]#

The time derivative, \(\dfrac{\partial}{\partial t}\), of this form.

wedge(other)[source]#

The wedge, \(\wedge\), between this form and another form.

The forms a and b are root forms since they are directly defined through make_form method. With these elementary forms, it is possible to build more complicated non-root forms through operators. Implemented operators are

Implemented operators for forms

operator

symbolic representation

usage

exterior derivative

\(\mathrm{d}\)

a.exterior_derivative() or ph.exteror_derivative(a) or ph.d(a)

codifferential

\(\mathrm{d}^\ast\)

a.codifferential() or ph.codifferential(a)

time derivative

\(\frac{\partial}{\partial t}\)

a.time_derivative() or ph.time_derivative(a)

wedge product

\(\wedge\)

Given two forms, a: \(\alpha\) and b: \(\beta\), The wedge product between them, i.e. \(\alpha\wedge\beta\), is a.wedge(b) or ph.wedge(a, b).

inner product

\(\left(\cdot,\cdot\right)\)

Given two forms, a: \(\alpha\) and b: \(\beta\), The inner product between them, i.e. \(\left(\alpha,\beta\right)\), is ph.inner(a,b).

Hodge

\(\star\)

ph.Hodge(a)

trace

\(\mathrm{tr}\)

ph.trace(a)

For example,

>>> da_dt = a.time_derivative()
>>> db_dt = b.time_derivative()
>>> cd_a = a.codifferential()
>>> d_b = b.exterior_derivative()

This generates four more forms, da_dt, db_dt, cd_a and d_b, which are

  • time derivative of a

  • time derivative of b

  • codifferential of a

  • exterior derivative of b

respectively. These non-root forms will appear in the form list if you do

>>> ph.list_forms()
<Figure size ...

All these forms, both root and non-root ones, are the ingredients for making partial differential equaitons (DPE) which is introduced in the next section.


↩️ Back to Documentations.