Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed some issues with transfer classes #422

Merged
merged 4 commits into from
Apr 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pySDC/helpers/transfer_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def restriction_matrix_1d(fine_grid, coarse_grid, k=2, periodic=False, pad=1):

def interpolation_matrix_1d(fine_grid, coarse_grid, k=2, periodic=False, pad=1, equidist_nested=True):
"""
Function to contruct the restriction matrix in 1d using barycentric interpolation
Function to construct the restriction matrix in 1d using barycentric interpolation
Args:
fine_grid (np.ndarray): a one dimensional 1d array containing the nodes of the fine grid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
class CheckIterationEstimatorNonMPI(ConvergenceController):
def __init__(self, controller, params, description, **kwargs):
"""
Initalization routine
Initialization routine

Args:
controller (pySDC.Controller): The controller
Expand Down
2 changes: 1 addition & 1 deletion pySDC/implementations/datatype_classes/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ def __new__(cls, init, *args, **kwargs):
def __getattr__(self, name):
if name in self.components:
if self.shape[0] == len(self.components):
return self[self.components.index(name)]
return self[self.components.index(name)].view(mesh)
else:
raise AttributeError(f'Cannot access {name!r} in {type(self)!r} because the shape is unexpected.')
else:
Expand Down
1 change: 1 addition & 0 deletions pySDC/implementations/problem_classes/Brusselator.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def __init__(self, alpha=0.1, **kwargs):
shape = (2,) + (self.init[0])
self.iU = 0
self.iV = 1
self.ncomp = 2 # needed for transfer class
self.init = (shape, self.comm, np.dtype('float'))

def _eval_explicit_part(self, u, t, f_expl):
Expand Down
1 change: 1 addition & 0 deletions pySDC/implementations/problem_classes/GrayScott_MPIFFT.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def __init__(self, Du=1.0, Dv=0.01, A=0.09, B=0.086, **kwargs):
shape = (2,) + (self.init[0])
self.iU = 0
self.iV = 1
self.ncomp = 2 # needed for transfer class
self.init = (shape, self.comm, self.xp.dtype('float'))

self._makeAttributeAndRegister('Du', 'Dv', 'A', 'B', localVars=locals(), readOnly=True)
Expand Down
8 changes: 3 additions & 5 deletions pySDC/implementations/sweeper_classes/imex_1st_order.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,14 @@ def integrate(self):
list of dtype_u: containing the integral as values
"""

# get current level and problem description
L = self.level
P = L.prob

me = []

# integrate RHS over all collocation nodes
for m in range(1, self.coll.num_nodes + 1):
me.append(L.dt * self.coll.Qmat[m, 1] * (L.f[1].impl + L.f[1].expl))
# new instance of dtype_u, initialize values with 0
for j in range(2, self.coll.num_nodes + 1):
me.append(P.dtype_u(P.init, val=0.0))
for j in range(1, self.coll.num_nodes + 1):
me[m - 1] += L.dt * self.coll.Qmat[m, j] * (L.f[j].impl + L.f[j].expl)

return me
Expand Down
132 changes: 46 additions & 86 deletions pySDC/implementations/transfer_classes/TransferMesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
import pySDC.helpers.transfer_helper as th
from pySDC.core.Errors import TransferError
from pySDC.core.SpaceTransfer import space_transfer
from pySDC.implementations.datatype_classes.mesh import mesh, imex_mesh, comp2_mesh


class mesh_to_mesh(space_transfer):
"""
Custon base_transfer class, implements Transfer.py
Custom base_transfer class, implements Transfer.py

This implementation can restrict and prolong between nd meshes with dirichlet-0 or periodic boundaries
via matrix-vector products
via matrix-vector products.

Attributes:
Rspace: spatial restriction matrix, dim. Nf x Nc
Expand All @@ -30,7 +29,7 @@ def __init__(self, fine_prob, coarse_prob, params):
"""

# invoke super initialization
super(mesh_to_mesh, self).__init__(fine_prob, coarse_prob, params)
super().__init__(fine_prob, coarse_prob, params)

if self.params.rorder % 2 != 0:
raise TransferError('Need even order for restriction')
Expand Down Expand Up @@ -153,51 +152,31 @@ def restrict(self, F):
Args:
F: the fine level data (easier to access than via the fine attribute)
"""
if isinstance(F, mesh):
G = self.coarse_prob.dtype_u(self.coarse_prob.init)
if hasattr(self.fine_prob, 'ncomp'):
for i in range(self.fine_prob.ncomp):
tmpF = F[..., i].flatten()
tmpG = self.Rspace.dot(tmpF)
G[..., i] = tmpG.reshape(self.coarse_prob.nvars)
else:
tmpF = F.flatten()
tmpG = self.Rspace.dot(tmpF)
G[:] = tmpG.reshape(self.coarse_prob.nvars)
elif isinstance(F, imex_mesh):
G = self.coarse_prob.dtype_f(self.coarse_prob.init)
if hasattr(self.fine_prob, 'ncomp'):
for i in range(self.fine_prob.ncomp):
tmpF = F.impl[..., i].flatten()
tmpG = self.Rspace.dot(tmpF)
G.impl[..., i] = tmpG.reshape(self.coarse_prob.nvars)
tmpF = F.expl[..., i].flatten()
tmpG = self.Rspace.dot(tmpF)
G.expl[..., i] = tmpG.reshape(self.coarse_prob.nvars)
else:
tmpF = F.impl.flatten()
tmpG = self.Rspace.dot(tmpF)
G.impl[:] = tmpG.reshape(self.coarse_prob.nvars)
tmpF = F.expl.flatten()
tmpG = self.Rspace.dot(tmpF)
G.expl[:] = tmpG.reshape(self.coarse_prob.nvars)
elif isinstance(F, comp2_mesh):
G = self.coarse_prob.dtype_f(self.coarse_prob.init)
G = type(F)(self.coarse_prob.init)

def _restrict(fine, coarse):
if hasattr(self.fine_prob, 'ncomp'):
for i in range(self.fine_prob.ncomp):
tmpF = F.comp1[..., i].flatten()
tmpG = self.Rspace.dot(tmpF)
G.comp1[..., i] = tmpG.reshape(self.coarse_prob.nvars)
tmpF = F.comp2[..., i].flatten()
tmpG = self.Rspace.dot(tmpF)
G.comp2[..., i] = tmpG.reshape(self.coarse_prob.nvars)
if fine.shape[-1] == self.fine_prob.ncomp:
tmpF = fine[..., i].flatten()
tmpG = self.Rspace.dot(tmpF)
coarse[..., i] = tmpG.reshape(self.coarse_prob.nvars)
elif fine.shape[0] == self.fine_prob.ncomp:
tmpF = fine[i, ...].flatten()
tmpG = self.Rspace.dot(tmpF)
coarse[i, ...] = tmpG.reshape(self.coarse_prob.nvars)
else:
raise TransferError('Don\'t know how to restrict for this problem with multiple components')
else:
tmpF = F.comp1.flatten()
tmpG = self.Rspace.dot(tmpF)
G.comp1[:] = tmpG.reshape(self.coarse_prob.nvars)
tmpF = F.comp2.flatten()
tmpF = fine.flatten()
tmpG = self.Rspace.dot(tmpF)
G.comp2[:] = tmpG.reshape(self.coarse_prob.nvars)
coarse[:] = tmpG.reshape(self.coarse_prob.nvars)

if hasattr(type(F), 'components'):
for comp in F.components:
_restrict(F.__getattr__(comp), G.__getattr__(comp))
elif type(F).__name__ == 'mesh':
_restrict(F, G)
else:
raise TransferError('Wrong data type for restriction, got %s' % type(F))
return G
Expand All @@ -208,51 +187,32 @@ def prolong(self, G):
Args:
G: the coarse level data (easier to access than via the coarse attribute)
"""
if isinstance(G, mesh):
F = self.fine_prob.dtype_u(self.fine_prob.init)
if hasattr(self.fine_prob, 'ncomp'):
for i in range(self.fine_prob.ncomp):
tmpG = G[..., i].flatten()
tmpF = self.Pspace.dot(tmpG)
F[..., i] = tmpF.reshape(self.fine_prob.nvars)
else:
tmpG = G.flatten()
tmpF = self.Pspace.dot(tmpG)
F[:] = tmpF.reshape(self.fine_prob.nvars)
elif isinstance(G, imex_mesh):
F = self.fine_prob.dtype_f(self.fine_prob.init)
if hasattr(self.fine_prob, 'ncomp'):
for i in range(self.fine_prob.ncomp):
tmpG = G.impl[..., i].flatten()
tmpF = self.Pspace.dot(tmpG)
F.impl[..., i] = tmpF.reshape(self.fine_prob.nvars)
tmpG = G.expl[..., i].flatten()
tmpF = self.Rspace.dot(tmpG)
F.expl[..., i] = tmpF.reshape(self.fine_prob.nvars)
else:
tmpG = G.impl.flatten()
tmpF = self.Pspace.dot(tmpG)
F.impl[:] = tmpF.reshape(self.fine_prob.nvars)
tmpG = G.expl.flatten()
tmpF = self.Pspace.dot(tmpG)
F.expl[:] = tmpF.reshape(self.fine_prob.nvars)
elif isinstance(G, comp2_mesh):
F = self.fine_prob.dtype_f(self.fine_prob.init)
F = type(G)(self.fine_prob.init)

def _prolong(coarse, fine):
if hasattr(self.fine_prob, 'ncomp'):
for i in range(self.fine_prob.ncomp):
tmpG = G.comp1[..., i].flatten()
tmpF = self.Pspace.dot(tmpG)
F.comp1[..., i] = tmpF.reshape(self.fine_prob.nvars)
tmpG = G.comp2[..., i].flatten()
tmpF = self.Rspace.dot(tmpG)
F.comp2[..., i] = tmpF.reshape(self.fine_prob.nvars)
if coarse.shape[-1] == self.fine_prob.ncomp:
tmpG = coarse[..., i].flatten()
tmpF = self.Pspace.dot(tmpG)
fine[..., i] = tmpF.reshape(self.fine_prob.nvars)
elif coarse.shape[0] == self.fine_prob.ncomp:
tmpG = coarse[i, ...].flatten()
tmpF = self.Pspace.dot(tmpG)
fine[i, ...] = tmpF.reshape(self.fine_prob.nvars)
else:
raise TransferError('Don\'t know how to prolong for this problem with multiple components')
else:
tmpG = G.comp1.flatten()
tmpF = self.Pspace.dot(tmpG)
F.comp1[:] = tmpF.reshape(self.fine_prob.nvars)
tmpG = G.comp2.flatten()
tmpG = coarse.flatten()
tmpF = self.Pspace.dot(tmpG)
F.comp2[:] = tmpF.reshape(self.fine_prob.nvars)
fine[:] = tmpF.reshape(self.fine_prob.nvars)
return fine

if hasattr(type(F), 'components'):
for comp in G.components:
_prolong(G.__getattr__(comp), F.__getattr__(comp))
elif type(G).__name__ == 'mesh':
F[:] = _prolong(G, F)
else:
raise TransferError('Wrong data type for prolongation, got %s' % type(G))
return F
50 changes: 21 additions & 29 deletions pySDC/implementations/transfer_classes/TransferMesh_FFT.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from pySDC.core.Errors import TransferError
from pySDC.core.SpaceTransfer import space_transfer
from pySDC.implementations.datatype_classes.mesh import mesh, imex_mesh


class mesh_to_mesh_fft(space_transfer):
Expand All @@ -26,9 +25,9 @@ def __init__(self, fine_prob, coarse_prob, params):
params: parameters for the transfer operators
"""
# invoke super initialization
super(mesh_to_mesh_fft, self).__init__(fine_prob, coarse_prob, params)
super().__init__(fine_prob, coarse_prob, params)

self.ratio = int(self.fine_prob.params.nvars / self.coarse_prob.params.nvars)
self.ratio = int(self.fine_prob.nvars / self.coarse_prob.nvars)

def restrict(self, F):
"""
Expand All @@ -37,11 +36,11 @@ def restrict(self, F):
Args:
F: the fine level data (easier to access than via the fine attribute)
"""
if isinstance(F, mesh):
G = mesh(self.coarse_prob.init, val=0.0)
G = type(F)(self.coarse_prob.init, val=0.0)

if type(F).__name__ == 'mesh':
G[:] = F[:: self.ratio]
elif isinstance(F, imex_mesh):
G = imex_mesh(self.coarse_prob.init, val=0.0)
elif type(F).__name__ == 'imex_mesh':
G.impl[:] = F.impl[:: self.ratio]
G.expl[:] = F.expl[:: self.ratio]
else:
Expand All @@ -55,28 +54,21 @@ def prolong(self, G):
Args:
G: the coarse level data (easier to access than via the coarse attribute)
"""
if isinstance(G, mesh):
F = mesh(self.fine_prob.init, val=0.0)
tmpG = np.fft.rfft(G)
tmpF = np.zeros(self.fine_prob.init[0] // 2 + 1, dtype=np.complex128)
halfG = int(self.coarse_prob.init[0] / 2)
tmpF[0:halfG] = tmpG[0:halfG]
tmpF[-1] = tmpG[-1]
F[:] = np.fft.irfft(tmpF) * self.ratio
elif isinstance(G, imex_mesh):
F = imex_mesh(G)
tmpG_impl = np.fft.rfft(G.impl)
tmpF_impl = np.zeros(self.fine_prob.init[0] // 2 + 1, dtype=np.complex128)
halfG = int(self.coarse_prob.init[0] / 2)
tmpF_impl[0:halfG] = tmpG_impl[0:halfG]
tmpF_impl[-1] = tmpG_impl[-1]
F.impl[:] = np.fft.irfft(tmpF_impl) * self.ratio
tmpG_expl = np.fft.rfft(G.expl)
tmpF_expl = np.zeros(self.fine_prob.init[0] // 2 + 1, dtype=np.complex128)
halfG = int(self.coarse_prob.init[0] / 2)
tmpF_expl[0:halfG] = tmpG_expl[0:halfG]
tmpF_expl[-1] = tmpG_expl[-1]
F.expl[:] = np.fft.irfft(tmpF_expl) * self.ratio
F = type(G)(self.fine_prob.init, val=0.0)

def _prolong(coarse):
coarse_hat = np.fft.rfft(coarse)
fine_hat = np.zeros(self.fine_prob.init[0] // 2 + 1, dtype=np.complex128)
half_idx = self.coarse_prob.init[0] // 2
fine_hat[0:half_idx] = coarse_hat[0:half_idx]
fine_hat[-1] = coarse_hat[-1]
return np.fft.irfft(fine_hat) * self.ratio

if type(G).__name__ == 'mesh':
F[:] = _prolong(G)
elif type(G).__name__ == 'imex_mesh':
F.impl[:] = _prolong(G.impl)
F.expl[:] = _prolong(G.expl)
else:
raise TransferError('Unknown data type, got %s' % type(G))
return F
Loading
Loading