Skip to content

Commit 44b4cb9

Browse files
committed
Merge branch 'second_order'
2 parents edad2ca + 14be9be commit 44b4cb9

32 files changed

+1259
-157
lines changed

.travis.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,12 @@ before_install:
1818
install:
1919
- conda install --yes python=${TRAVIS_PYTHON_VERSION} numpy future scipy matplotlib nose pep8 coverage mpi4py sympy dill numba
2020
- conda install --yes python=${TRAVIS_PYTHON_VERSION} sphinx=1.6.3
21-
- conda list
2221
- pip install --user coloredlogs
23-
- pip install --user travis-sphinx
22+
- if [[ $PYTHON_VERSION == 3 ]]; then pip install --user travis-sphinx; fi
2423
- sudo apt-get install -y texlive-latex-recommended texlive-fonts-recommended texlive-latex-extra dvipng
2524

2625
script:
2726
- "./docs/update_apidocs.sh"
28-
- which nosetests
2927
- nosetests --with-coverage --cover-erase --cover-inclusive --cover-package=pySDC/core,pySDC/implementations,pySDC/helpers,pySDC/tutorial --cover-html --cover-html-dir=doc/build/test_coverage pySDC/tests
3028
- if [[ $PYTHON_VERSION == 3 ]]; then travis-sphinx build; fi
3129

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ Projects
9595
projects/RDC.rst
9696
projects/asymp_conv.rst
9797
projects/matrixPFASST.rst
98+
projects/Hamiltonian.rst
9899

99100

100101
Tests
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.. include:: /../../pySDC/projects/Hamiltonian/README.rst
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Full code: `pySDC/projects/Hamiltonian/simple_problems.py <https://github.com/Parallel-in-Time/pySDC/blob/master/pySDC/projects/Hamiltonian/simple_problems.py>`_
2+
3+
.. literalinclude:: ../../../pySDC/projects/Hamiltonian/simple_problems.py
4+
5+
Results:
6+
7+
.. image:: ../../../data/harmonic_hamiltonian.png
8+
:scale: 50 %
9+
10+
.. image:: ../../../data/henonheiles_hamiltonian.png
11+
:scale: 50 %
12+
13+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
Full code: `pySDC/projects/Hamiltonian/solar_system.py <https://github.com/Parallel-in-Time/pySDC/blob/master/pySDC/projects/Hamiltonian/solar_system.py>`_
2+
3+
.. literalinclude:: ../../../pySDC/projects/Hamiltonian/solar_system.py
4+
5+
Results:
6+
7+
.. image:: ../../../data/outer_solar_system_hamiltonian.png
8+
:scale: 50 %
9+
.. image:: ../../../data/outer_solar_system_positions.png
10+
:scale: 50 %

pySDC/core/Sweeper.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ def get_Qdelta_explicit(self, coll, qd_type):
114114
QDmat[m, 0:m] = self.coll.delta_m[0:m]
115115
elif qd_type == 'GS':
116116
QDmat = np.tril(self.coll.Qmat, k=-1)
117+
elif qd_type == 'PIC':
118+
QDmat = np.zeros(coll.Qmat.shape)
117119
else:
118120
raise NotImplementedError('qd_type explicit not implemented')
119121

pySDC/helpers/plot_helper.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ def setup_mpl():
4545
"pgf.preamble": [
4646
r"\usepackage[utf8x]{inputenc}", # use utf8 fonts becasue your computer can handle it :)
4747
r"\usepackage[T1]{fontenc}", # plots will be generated using this preamble
48+
r"\usepackage{underscore}",
4849
]
4950
}
5051
mpl.rcParams.update(pgf_with_latex)

pySDC/implementations/datatype_classes/particles.py

Lines changed: 76 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ def __init__(self, init=None, val=None):
3939
if isinstance(init, type(self)):
4040
self.values = cp.deepcopy(init.values)
4141
# if init is a number, create position object with val as initial value
42-
elif isinstance(init, int):
43-
self.values = np.empty(3 * init)
42+
elif isinstance(init, int) or isinstance(init, tuple):
43+
self.values = np.empty(init)
4444
self.values[:] = val
4545
# something is wrong, if none of the ones above hit
4646
else:
@@ -60,7 +60,7 @@ def __add__(self, other):
6060

6161
if isinstance(other, type(self)):
6262
# always create new position, since otherwise c = a + b changes a as well!
63-
pos = particles.position(int(np.size(self.values) / 3))
63+
pos = particles.position(self.values.shape)
6464
pos.values = self.values + other.values
6565
return pos
6666
else:
@@ -80,7 +80,7 @@ def __sub__(self, other):
8080

8181
if isinstance(other, type(self)):
8282
# always create new position, since otherwise c = a - b changes a as well!
83-
pos = particles.position(int(np.size(self.values) / 3))
83+
pos = particles.position(self.values.shape)
8484
pos.values = self.values - other.values
8585
return pos
8686
else:
@@ -100,7 +100,7 @@ def __rmul__(self, other):
100100

101101
if isinstance(other, float):
102102
# create new position
103-
pos = particles.position(int(np.size(self.values) / 3))
103+
pos = particles.position(self.values.shape)
104104
pos.values = self.values * other
105105
return pos
106106
else:
@@ -138,8 +138,8 @@ def __init__(self, init=None, val=None):
138138
if isinstance(init, type(self)):
139139
self.values = cp.deepcopy(init.values)
140140
# if init is a number, create velocity object with val as initial value
141-
elif isinstance(init, int):
142-
self.values = np.empty(3 * init)
141+
elif isinstance(init, int) or isinstance(init, tuple):
142+
self.values = np.empty(init)
143143
self.values[:] = val
144144
# something is wrong, if none of the ones above hit
145145
else:
@@ -159,7 +159,7 @@ def __add__(self, other):
159159

160160
if isinstance(other, type(self)):
161161
# always create new position, since otherwise c = a + b changes a as well!
162-
vel = particles.velocity(int(np.size(self.values) / 3))
162+
vel = particles.velocity(self.values.shape)
163163
vel.values = self.values + other.values
164164
return vel
165165
else:
@@ -179,7 +179,7 @@ def __sub__(self, other):
179179

180180
if isinstance(other, type(self)):
181181
# always create new position, since otherwise c = a - b changes a as well!
182-
vel = particles.velocity(int(np.size(self.values) / 3))
182+
vel = particles.velocity(self.values.shape)
183183
vel.values = self.values - other.values
184184
return vel
185185
else:
@@ -199,7 +199,7 @@ def __rmul__(self, other):
199199

200200
if isinstance(other, float):
201201
# create new position, interpret float factor as time (time x velocity = position)
202-
pos = particles.position(int(np.size(self.values) / 3))
202+
pos = particles.position(self.values.shape)
203203
pos.values = self.values * other
204204
return pos
205205
else:
@@ -215,13 +215,13 @@ def __abs__(self):
215215
# FIXME: is this a good idea for multiple particles?
216216
return np.amax(np.absolute(self.values))
217217

218-
def __init__(self, init=None, vals=(None, None, None, None)):
218+
def __init__(self, init=None, val=None):
219219
"""
220220
Initialization routine
221221
222222
Args:
223223
init: can either be a number or another particle object
224-
vals: initial tuple of values for position and velocity (default: (None,None))
224+
val: initial tuple of values for position and velocity (default: (None,None))
225225
Raises:
226226
DataError: if init is none of the types above
227227
"""
@@ -234,12 +234,39 @@ def __init__(self, init=None, vals=(None, None, None, None)):
234234
self.m = cp.deepcopy(init.m)
235235
# if init is a number, create particles object and pick the corresponding initial values
236236
elif isinstance(init, int):
237-
self.pos = particles.position(init, val=vals[0])
238-
self.vel = particles.velocity(init, val=vals[1])
239-
self.q = np.zeros(int(np.size(self.pos.values) / 3))
240-
self.q[:] = vals[2]
241-
self.m = np.zeros(int(np.size(self.pos.values) / 3))
242-
self.m[:] = vals[3]
237+
if isinstance(val, int) or val is None:
238+
self.pos = particles.position(init, val=val)
239+
self.vel = particles.velocity(init, val=val)
240+
self.q = np.zeros(init)
241+
self.q[:] = val
242+
self.m = np.zeros(init)
243+
self.m[:] = val
244+
elif isinstance(val, tuple) and len(val) == 4:
245+
self.pos = particles.position(init, val=val[0])
246+
self.vel = particles.velocity(init, val=val[1])
247+
self.q = np.zeros(init)
248+
self.q[:] = val[2]
249+
self.m = np.zeros(init)
250+
self.m[:] = val[3]
251+
else:
252+
raise DataError('type of val is wrong, got %s', val)
253+
elif isinstance(init, tuple):
254+
if isinstance(val, int) or val is None:
255+
self.pos = particles.position(init, val=val)
256+
self.vel = particles.velocity(init, val=val)
257+
self.q = np.zeros(init[-1])
258+
self.q[:] = val
259+
self.m = np.zeros(init[-1])
260+
self.m[:] = val
261+
elif isinstance(val, tuple) and len(val) == 4:
262+
self.pos = particles.position(init, val=val[0])
263+
self.vel = particles.velocity(init, val=val[1])
264+
self.q = np.zeros(init[-1])
265+
self.q[:] = val[2]
266+
self.m = np.zeros(init[-1])
267+
self.m[:] = val[3]
268+
else:
269+
raise DataError('type of val is wrong, got %s', val)
243270
# something is wrong, if none of the ones above hit
244271
else:
245272
raise DataError('something went wrong during %s initialization' % type(self))
@@ -258,7 +285,7 @@ def __add__(self, other):
258285

259286
if isinstance(other, type(self)):
260287
# always create new particles, since otherwise c = a + b changes a as well!
261-
p = particles(int(np.size(self.pos.values) / 3))
288+
p = particles(self.pos.values.shape)
262289
p.pos = self.pos + other.pos
263290
p.vel = self.vel + other.vel
264291
p.m = self.m
@@ -281,7 +308,7 @@ def __sub__(self, other):
281308

282309
if isinstance(other, type(self)):
283310
# always create new particles, since otherwise c = a - b changes a as well!
284-
p = particles(int(np.size(self.pos.values) / 3))
311+
p = particles(self.pos.values.shape)
285312
p.pos = self.pos - other.pos
286313
p.vel = self.vel - other.vel
287314
p.m = self.m
@@ -304,7 +331,7 @@ def __rmul__(self, other):
304331

305332
if isinstance(other, float):
306333
# always create new particles
307-
p = particles(int(np.size(self.pos.values) / 3))
334+
p = particles(self.pos.values.shape)
308335
p.pos = other * self.pos
309336
p.vel.values = other * self.vel.values
310337
p.m = self.m
@@ -348,8 +375,8 @@ def __init__(self, init=None, val=None):
348375
if isinstance(init, acceleration):
349376
self.values = cp.deepcopy(init.values)
350377
# if init is a number, create acceleration object with val as initial value
351-
elif isinstance(init, int):
352-
self.values = np.empty(3 * init)
378+
elif isinstance(init, int) or isinstance(init, tuple):
379+
self.values = np.empty(init)
353380
self.values[:] = val
354381
# something is wrong, if none of the ones above hit
355382
else:
@@ -369,7 +396,7 @@ def __add__(self, other):
369396

370397
if isinstance(other, type(self)):
371398
# always create new acceleration, since otherwise c = a + b changes a as well!
372-
acc = acceleration(int(np.size(self.values) / 3))
399+
acc = acceleration(self.values.shape)
373400
acc.values = self.values + other.values
374401
return acc
375402
else:
@@ -389,7 +416,7 @@ def __rmul__(self, other):
389416

390417
if isinstance(other, float):
391418
# create new velocity, interpret float factor as time (time x acceleration = velocity)
392-
vel = particles.velocity(int(np.size(self.values) / 3))
419+
vel = particles.velocity(self.values.shape)
393420
vel.values = self.values * other
394421
return vel
395422
else:
@@ -430,8 +457,8 @@ def __init__(self, init=None, val=None):
430457
if isinstance(init, type(self)):
431458
self.values = cp.deepcopy(init.values)
432459
# if init is a number, create electric object with val as initial value
433-
elif isinstance(init, int):
434-
self.values = np.empty(3 * init)
460+
elif isinstance(init, int) or isinstance(init, tuple):
461+
self.values = np.empty(init)
435462
self.values[:] = val
436463
# something is wrong, if none of the ones above hit
437464
else:
@@ -451,7 +478,7 @@ def __add__(self, other):
451478

452479
if isinstance(other, type(self)):
453480
# always create new electric, since otherwise c = a + b changes a as well!
454-
E = fields.electric(int(np.size(self.values) / 3))
481+
E = fields.electric(self.values.shape)
455482
E.values = self.values + other.values
456483
return E
457484
else:
@@ -471,7 +498,7 @@ def __sub__(self, other):
471498

472499
if isinstance(other, type(self)):
473500
# always create new electric, since otherwise c = a + b changes a as well!
474-
E = fields.electric(int(np.size(self.values) / 3))
501+
E = fields.electric(self.values.shape)
475502
E.values = self.values - other.values
476503
return E
477504
else:
@@ -491,7 +518,7 @@ def __rmul__(self, other):
491518

492519
if isinstance(other, float):
493520
# create new electric, no specific interpretation of float factor
494-
E = fields.electric(int(np.size(self.values) / 3))
521+
E = fields.electric(self.values.shape)
495522
E.values = self.values * other
496523
return E
497524
else:
@@ -520,8 +547,8 @@ def __init__(self, init=None, val=None):
520547
if isinstance(init, type(self)):
521548
self.values = cp.deepcopy(init.values)
522549
# if init is a number, create magnetic object with val as initial value
523-
elif isinstance(init, int):
524-
self.values = np.empty(3 * init)
550+
elif isinstance(init, int) or isinstance(init, tuple):
551+
self.values = np.empty(init)
525552
self.values[:] = val
526553
# something is wrong, if none of the ones above hit
527554
else:
@@ -541,7 +568,7 @@ def __add__(self, other):
541568

542569
if isinstance(other, type(self)):
543570
# always create new magnetic, since otherwise c = a + b changes a as well!
544-
M = fields.magnetic(int(np.size(self.values) / 3))
571+
M = fields.magnetic(self.values.shape)
545572
M.values = self.values + other.values
546573
return M
547574
else:
@@ -561,7 +588,7 @@ def __sub__(self, other):
561588

562589
if isinstance(other, type(self)):
563590
# always create new magnetic, since otherwise c = a + b changes a as well!
564-
M = fields.magnetic(int(np.size(self.values) / 3))
591+
M = fields.magnetic(self.values.shape)
565592
M.values = self.values - other.values
566593
return M
567594
else:
@@ -581,19 +608,19 @@ def __rmul__(self, other):
581608

582609
if isinstance(other, float):
583610
# create new magnetic, no specific interpretation of float factor
584-
M = fields.magnetic(int(np.size(self.values) / 3))
611+
M = fields.magnetic(self.values.shape)
585612
M.values = self.values * other
586613
return M
587614
else:
588615
raise DataError("Type error: cannot multiply %s to %s" % (type(other), type(self)))
589616

590-
def __init__(self, init=None, vals=(None, None)):
617+
def __init__(self, init=None, val=None):
591618
"""
592619
Initialization routine
593620
594621
Args:
595622
init: can either be a number or another fields object
596-
vals: initial tuple of values for electric and magnetic (default: (None,None))
623+
val: initial tuple of values for electric and magnetic (default: (None,None))
597624
Raises:
598625
DataError: if init is none of the types above
599626
"""
@@ -603,9 +630,15 @@ def __init__(self, init=None, vals=(None, None)):
603630
self.elec = fields.electric(init.elec)
604631
self.magn = fields.magnetic(init.magn)
605632
# if init is a number, create fields object and pick the corresponding initial values
606-
elif isinstance(init, int):
607-
self.elec = fields.electric(init, val=vals[0])
608-
self.magn = fields.magnetic(init, val=vals[1])
633+
elif isinstance(init, int) or isinstance(init, tuple):
634+
if isinstance(val, int) or val is None:
635+
self.elec = fields.electric(init, val=val)
636+
self.magn = fields.magnetic(init, val=val)
637+
elif isinstance(val, tuple) and len(val) == 2:
638+
self.elec = fields.electric(init, val=val[0])
639+
self.magn = fields.magnetic(init, val=val[1])
640+
else:
641+
raise DataError('wrong type of val, got %s' % val)
609642
# something is wrong, if none of the ones above hit
610643
else:
611644
raise DataError('something went wrong during %s initialization' % type(self))
@@ -624,7 +657,7 @@ def __add__(self, other):
624657

625658
if isinstance(other, type(self)):
626659
# always create new fields, since otherwise c = a - b changes a as well!
627-
p = fields(int(np.size(self.elec.values) / 3))
660+
p = fields(self.elec.values.shape)
628661
p.elec = self.elec + other.elec
629662
p.magn = self.magn + other.magn
630663
return p
@@ -645,7 +678,7 @@ def __sub__(self, other):
645678

646679
if isinstance(other, type(self)):
647680
# always create new fields, since otherwise c = a - b changes a as well!
648-
p = fields(int(np.size(self.elec.values) / 3))
681+
p = fields(self.elec.values.shape)
649682
p.elec = self.elec - other.elec
650683
p.magn = self.magn - other.magn
651684
return p
@@ -666,7 +699,7 @@ def __rmul__(self, other):
666699

667700
if isinstance(other, float):
668701
# always create new fields, since otherwise c = a - b changes a as well!
669-
p = fields(int(np.size(self.elec.values) / 3))
702+
p = fields(self.elec.values.shape)
670703
p.elec = other * self.elec
671704
p.magn = other * self.magn
672705
return p

0 commit comments

Comments
 (0)