Step 1 : generate \(Q\)-coefficients
📜 We denote by \(Q\)-coefficients (or Butcher table) what fully describes a multi-stage time stepping scheme (or Runge-Kutta method):
where \(\tau\) are the nodes, \(w\) the weights and \(Q\) … well, the \(Q\) matrix.
There is two approaches in qmat to generate those coefficients for many time-stepping schemes, from which you can choose depending on your needs and preferences.
Use a generic function
First, you can simply import the following :
[1]:
from qmat import genQCoeffs
Then generate \(Q\)-coefficients like this :
[2]:
# Coefficients or a collocation method
nodes, weights, Q = genQCoeffs("Collocation", nNodes=4, nodeType="LEGENDRE", quadType="RADAU-RIGHT")
print("node : ", nodes)
print("weights : ", weights)
print("Q : ")
print(Q)
node : [0.08858796 0.40946686 0.78765946 1. ]
weights : [0.22046221 0.38819347 0.32884432 0.0625 ]
Q :
[[ 0.11299948 -0.04030922 0.02580238 -0.00990468]
[ 0.234384 0.20689257 -0.04785713 0.01604742]
[ 0.21668178 0.40612326 0.18903652 -0.0241821 ]
[ 0.22046221 0.38819347 0.32884432 0.0625 ]]
[3]:
# Coefficients of a Runge-Kutta method (Butcher table)
c, b, A = genQCoeffs("RK4")
print("c : ", c)
print("b : ", b)
print("A : ")
print(A)
c : [0. 0.5 0.5 1. ]
b : [0.16666667 0.33333333 0.33333333 0.16666667]
A :
[[0. 0. 0. 0. ]
[0.5 0. 0. 0. ]
[0. 0.5 0. 0. ]
[0. 0. 1. 0. ]]
Depending on its first given argument, genQCoeffs uses the associated \(Q\)-generator, potentially passing keyword arguments to instantiate.
📜 Checkout the tutorial on nodes generation for details about
nodeTypeandquadType.
If some generator arguments are missing or wrongly given, then a descriptive error is raised, for instance :
[4]:
try:
nodes, weights, Q = genQCoeffs("Collocation", nNodes=4, node_type="LEGENDRE", quadType="RADAU-RIGHT")
except Exception as e:
print(f"{e.__class__.__name__}: {e}")
TypeError: Collocation.__init__() got an unexpected keyword argument 'node_type'. Did you mean 'nodeType'?
[5]:
try:
nodes, weights, Q = genQCoeffs("Collocation", nNodes=4, nodeType="LEGENDRE")
except Exception as e:
print(f"{e.__class__.__name__}: {e}")
TypeError: Collocation.__init__() missing 1 required positional argument: 'quadType'
🔔 Note that different aliases exists for each generators. For instance :
[6]:
# alias for Collocation
nodes, weights, Q = genQCoeffs("coll", nNodes=4, nodeType="LEGENDRE", quadType="RADAU-RIGHT")
# alias for RK4
c, b, A = genQCoeffs("ERK4")
All those aliases are uniques among \(Q\)-generators, and if the requested alias does not correspond to any generator, an appropriate error is raised :
[7]:
try:
genQCoeffs("collocation")
except Exception as e:
print(f"{e.__class__.__name__}: {e}")
ValueError: qType='collocation' is not available
Don’t hesitate to look at the API documentation for a full list of available generators …
Use generator objects
You can also directly use the generator classes, either by
importing the generator directly from its submodule
[8]:
from qmat.qcoeff.collocation import Collocation
coll = Collocation(nNodes=4, nodeType="LEGENDRE", quadType="RADAU-RIGHT")
retrieving it with one of its aliases from the
Q_GENERATORSdictionary
[9]:
from qmat import Q_GENERATORS
Generator = Q_GENERATORS["coll"]
coll = Generator(nNodes=4, nodeType="LEGENDRE", quadType="RADAU-RIGHT")
In both case, you’ll instantiate an object that provides properties to access each of the given coefficients :
[10]:
print("nodes :", coll.nodes)
print("weights :", coll.weights)
print("Q :")
print(coll.Q)
nodes : [0.08858796 0.40946686 0.78765946 1. ]
weights : [0.22046221 0.38819347 0.32884432 0.0625 ]
Q :
[[ 0.11299948 -0.04030922 0.02580238 -0.00990468]
[ 0.234384 0.20689257 -0.04785713 0.01604742]
[ 0.21668178 0.40612326 0.18903652 -0.0241821 ]
[ 0.22046221 0.38819347 0.32884432 0.0625 ]]
… or a genCoeffs method providing all coefficients, used similarly as the genQCoeffs function :
[11]:
nodes, weights, Q = coll.genCoeffs()
Finally, you can use those coefficients to build a Runge-Kutta type time-stepper…