From c9c5586eb5af4564d2eba71b8313c9584756ddcd Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Keck <Jean-Baptiste.Keck@imag.fr> Date: Tue, 20 Nov 2018 17:09:19 +0100 Subject: [PATCH] added diffusion to poisson curl --- .../particles_above_salt_bc.py | 17 ++-- .../particles_above_salt_bc_3d.py | 17 ++-- examples/taylor_green/taylor_green.py | 34 ++----- .../device/opencl/operator/poisson_curl.py | 98 +++++++++++-------- hysop/operator/base/poisson_curl.py | 10 +- 5 files changed, 86 insertions(+), 90 deletions(-) diff --git a/examples/particles_above_salt/particles_above_salt_bc.py b/examples/particles_above_salt/particles_above_salt_bc.py index b2684b87b..d662ea341 100644 --- a/examples/particles_above_salt/particles_above_salt_bc.py +++ b/examples/particles_above_salt/particles_above_salt_bc.py @@ -48,7 +48,8 @@ def compute(args): EnstrophyParameter, TimeParameters, \ VolumicIntegrationParameter from hysop.constants import Implementation, AdvectionCriteria, \ - BoxBoundaryCondition, BoundaryCondition + BoxBoundaryCondition, BoundaryCondition, \ + Backend from hysop.operators import DirectionalAdvection, DirectionalStretching, \ Diffusion, ComputeMeanField, \ @@ -181,13 +182,6 @@ def compute(args): raise RuntimeError(msg) #> Diffusion of vorticity, S and C - diffuse_W = Diffusion(implementation=impl, - name='diffuse_{}'.format(vorti.name), - pretty_name=u'diff{}'.format(vorti.pretty_name.decode('utf-8')), - nu = nu_W, - Fin = vorti, - variables = {vorti: npts}, - dt=dt, **extra_op_kwds) diffuse_S = Diffusion(implementation=impl, name='diffuse_S', pretty_name='diffS', @@ -226,6 +220,7 @@ def compute(args): #> Poisson operator to recover the velocity from the vorticity poisson = PoissonCurl(name='poisson', velocity=velo, vorticity=vorti, variables={velo:npts, vorti: npts}, + diffusion=nu_W, dt=dt, implementation=impl, **extra_op_kwds) #> Operator to compute the infinite norm of the velocity @@ -241,10 +236,12 @@ def compute(args): io_params = IOParams(filename='fields', frequency=args.dump_freq) dump_fields = HDF_Writer(name='dump', io_params=io_params, + force_backend=Backend.OPENCL, variables={velo: npts, vorti: npts, C: npts, - S: npts}) + S: npts}, + **extra_op_kwds) #> Operator to compute and save mean fields axes = list(range(0, dim-1)) @@ -287,7 +284,7 @@ def compute(args): problem = Problem(method=method) problem.insert(poisson, - diffuse_W, diffuse_S, diffuse_C, + diffuse_S, diffuse_C, splitting, dump_fields, compute_mean_fields, diff --git a/examples/particles_above_salt/particles_above_salt_bc_3d.py b/examples/particles_above_salt/particles_above_salt_bc_3d.py index 5beb1ffbd..ed1f96941 100644 --- a/examples/particles_above_salt/particles_above_salt_bc_3d.py +++ b/examples/particles_above_salt/particles_above_salt_bc_3d.py @@ -75,8 +75,8 @@ def compute(args): if (dim==2): (Sc, tau, Vp, Rs, Xo, Xn, N) = (0.70, 25, 0.04, 2.0, (-600,0), (600,750), (1537, 512)) elif (dim==3): - (Sc, tau, Vp, Rs, Xo, Xn, N) = (30.00, 25, 0.04, 2.0, (-110,0,0), (65,100,100), (3073, 1024, 1024)) - N = (257,64,64) + (Sc, tau, Vp, Rs, Xo, Xn, N) = (7.00, 25, 0.04, 2.0, (-110,0,0), (65,100,100), (3073, 1024, 1024)) + N = (513,128,128) else: raise NotImplementedError @@ -183,13 +183,6 @@ def compute(args): raise RuntimeError(msg) #> Diffusion of vorticity, S and C - diffuse_W = Diffusion(implementation=impl, - name='diffuse_{}'.format(vorti.name), - pretty_name=u'diff{}'.format(vorti.pretty_name.decode('utf-8')), - nu = nu_W, - Fin = vorti, - variables = {vorti: npts}, - dt=dt, **extra_op_kwds) diffuse_S = Diffusion(implementation=impl, name='diffuse_S', pretty_name='diffS', @@ -228,6 +221,7 @@ def compute(args): #> Poisson operator to recover the velocity from the vorticity poisson = PoissonCurl(name='poisson', velocity=velo, vorticity=vorti, variables={velo:npts, vorti: npts}, + diffusion=nu_W, dt=dt, implementation=impl, **extra_op_kwds) #> Operator to compute the infinite norm of the velocity @@ -244,7 +238,8 @@ def compute(args): dump_fields = HDF_Writer(name='dump', io_params=io_params, force_backend=Backend.OPENCL, - variables={velo[0]: npts, + variables={vorti: npts, + velo: npts, C: npts, S: npts}, **extra_op_kwds) @@ -280,7 +275,7 @@ def compute(args): problem = Problem(method=method) problem.insert(poisson, dump_fields, - diffuse_W, diffuse_S, diffuse_C, + diffuse_S, diffuse_C, splitting, min_max_U, min_max_W, adapt_dt) problem.build() diff --git a/examples/taylor_green/taylor_green.py b/examples/taylor_green/taylor_green.py index 5aa860d65..7acc59e49 100644 --- a/examples/taylor_green/taylor_green.py +++ b/examples/taylor_green/taylor_green.py @@ -35,7 +35,8 @@ def init_vorticity(data, coords, component=None): def compute(args): from hysop import Box, Simulation, Problem, MPIParams from hysop.defaults import VelocityField, VorticityField, \ - EnstrophyParameter, TimeParameters + EnstrophyParameter, TimeParameters, \ + ViscosityParameter from hysop.constants import Implementation, AdvectionCriteria, StretchingCriteria from hysop.operators import DirectionalAdvection, DirectionalStretchingDiffusion, \ @@ -86,6 +87,7 @@ def compute(args): velo = VelocityField(domain=box, dtype=args.dtype) vorti = VorticityField(velocity=velo) enstrophy = EnstrophyParameter(dtype=args.dtype) + viscosity = ViscosityParameter(dtype=args.dtype, initial_value=(1.0/args.Re), const=True) ### Build the directional operators if (impl is Implementation.FORTRAN): @@ -124,34 +126,17 @@ def compute(args): vorticity = vorti, variables = {velo: npts, vorti: npts}, dt=dt, **extra_op_kwds) - #> Directional diffusion - if (impl is Implementation.OPENCL): - diffuse = None - diffuse_dir = DirectionalDiffusion(implementation=impl, - name='diffuse', - fields = vorti, - coeffs = (1.0/args.Re), - variables = {vorti: npts}, - dt=dt, **extra_op_kwds) - else: - diffuse = Diffusion( - implementation=impl, - name='diffuse', - Fin = vorti, - viscosity = (1.0/args.Re), - variables = {vorti: npts}, - dt=dt, **extra_op_kwds) - diffuse_dir = None ### Build standard operators #> Poisson operator to recover the velocity from the vorticity poisson = PoissonCurl(name='poisson', velocity=velo, vorticity=vorti, variables={velo:npts, vorti: npts}, projection=args.reprojection_frequency, + diffusion=viscosity, dt=dt, implementation=impl, **extra_op_kwds) #> We ask to dump the outputs of this operator - #poisson.dump_outputs(fields=(vorti,), frequency=args.dump_freq) - #poisson.dump_outputs(fields=(velo,), frequency=args.dump_freq) + poisson.dump_outputs(fields=(vorti,), frequency=args.dump_freq) + poisson.dump_outputs(fields=(velo,), frequency=args.dump_freq) #> Operator to compute the infinite norm of the velocity if (impl is Implementation.FORTRAN): @@ -171,7 +156,7 @@ def compute(args): #> Directional splitting operator subgraph splitting = StrangSplitting(splitting_dim=dim, order=args.strang_order) - splitting.push_operators(advec_dir, stretch_dir, diffuse_dir, min_max_gradU) + splitting.push_operators(advec_dir, stretch_dir, min_max_gradU) ### Adaptive timestep operator adapt_dt = AdaptiveTimeStep(dt, equivalent_CFL=True) @@ -269,8 +254,7 @@ def compute(args): } ) problem = Problem(method=method) - problem.insert(poisson, - advec, splitting, diffuse, + problem.insert(poisson, advec, splitting, min_max_U, min_max_W, enstrophy_op, adapt_dt, plot) problem.build() @@ -379,7 +363,7 @@ if __name__=='__main__': tstart=0.0, tend=20.01, dt=1e-5, cfl=0.5, lcfl=0.125, - dump_freq=100, dump_times=(), + dump_freq=0, dump_times=(), Re=1600.0) parser.run(compute) diff --git a/hysop/backend/device/opencl/operator/poisson_curl.py b/hysop/backend/device/opencl/operator/poisson_curl.py index 07671c9aa..d07cf5542 100644 --- a/hysop/backend/device/opencl/operator/poisson_curl.py +++ b/hysop/backend/device/opencl/operator/poisson_curl.py @@ -38,8 +38,8 @@ class OpenClPoissonCurl(SpectralPoissonCurlOperatorBase, OpenClSymbolic): Win = tuple(Ft.output_symbolic_array('{}in_hat'.format(Ft.field.var_name)) for Ft in W_Ft) Wout = tuple(Bt.input_symbolic_array('{}out_hat'.format(Bt.field.var_name)) if (Bt is not None) else None for Bt in W_Bt) Uout = tuple(Bt.input_symbolic_array('{}out_hat'.format(Bt.field.var_name)) for Bt in U_Bt) - K = tuple(tuple(self.tg._indexed_wave_numbers[kd] for kd in kd1[::-1]) for kd1 in kd1s) - KK = tuple(tuple(self.tg._indexed_wave_numbers[kd] for kd in kd2[::-1]) for kd2 in kd2s) + K = tuple(tuple(self.tg._indexed_wave_numbers[kd] for kd in kd1[::-1]) for kd1 in kd1s) + KK = tuple(tuple(self.tg._indexed_wave_numbers[kd] for kd in kd2[::-1]) for kd2 in kd2s) def mul(Ki, other): if Ki.Wn.is_complex: @@ -47,14 +47,21 @@ class OpenClPoissonCurl(SpectralPoissonCurlOperatorBase, OpenClSymbolic): else: return Ki*other + if self.should_diffuse: + nu, dt = self.nu.s, self.dt.s + for i,(win,wout,KKi) in enumerate(zip(Win,Wout,KK)): + F = sum(KKi) + expr = Assignment(wout, win / (1 - nu*dt*F)) + self.require_symbolic_kernel('diffusion_kernel__{}'.format(i), expr) + Win = Wout + exprs = () indices = local_indices_symbols[:dim] cond = LogicalAND(*tuple(LogicalEQ(idx,0) for idx in indices)) for i in xrange(wcomp): - e = sum(KK[i]) - e = Assignment(Win[i], Select(Win[i]/e,0,cond)) - exprs += (e,) - self.require_symbolic_kernel('poisson_kernel', *exprs) + F = sum(KK[i]) + expr = Assignment(Win[i], Select(Win[i]/F,0,cond)) + self.require_symbolic_kernel('poisson_kernel__{}'.format(i), expr) if (dim == 2): assert wcomp==1 @@ -81,34 +88,42 @@ class OpenClPoissonCurl(SpectralPoissonCurlOperatorBase, OpenClSymbolic): self._build_projection_kernel() self._build_poisson_curl_kernel() self._build_ghost_exchangers() + + def _build_diffusion_kernel(self): + if self.should_diffuse: + diffusion_filters = () + for i in xrange(self.W.nb_components): + knl, knl_kwds = \ + self.symbolic_kernels['diffusion_kernel__{}'.format(i)] + knl = functools.partial(knl, queue=self.cl_env.default_queue) + def F(knl=knl, knl_kwds=knl_kwds): + return knl(**knl_kwds()) + diffusion_filters += (F,) + self.diffusion_filters = diffusion_filters + else: + self.diffusion_filters = None def _build_poisson_curl_kernel(self): - filter_poisson, _ = self.symbolic_kernels['poisson_kernel'] - self.poisson_filter = functools.partial(filter_poisson, queue=self.cl_env.default_queue) - - F0, _ = self.symbolic_kernels['curl_kernel__0'] - F1, _ = self.symbolic_kernels['curl_kernel__1'] - if (self.dim==2): - curl_kernels = (F0,F1) - elif (self.dim==3): - F2, _ = self.symbolic_kernels['curl_kernel__2'] - curl_kernels = (F0,F1,F2) - else: - msg='dim={}'.format(self.dim) - raise NotImplementedError(msg) - assert len(curl_kernels)==len(self.U_backward_transforms) - self.curl_filters = tuple(functools.partial(Fi, queue=self.cl_env.default_queue) for Fi in curl_kernels) + poisson_filters = () + for i in xrange(self.W.nb_components): + knl, __ = self.symbolic_kernels['poisson_kernel__{}'.format(i)] + Fi = functools.partial(knl, queue=self.cl_env.default_queue) + poisson_filters += (Fi,) + + curl_filters = () + for i in xrange(self.U.nb_components): + knl, __ = self.symbolic_kernels['curl_kernel__{}'.format(i)] + Fi = functools.partial(knl, queue=self.cl_env.default_queue) + curl_filters += (Fi,) + + self.poisson_filters = poisson_filters + self.curl_filters = curl_filters def _build_projection_kernel(self): if self.should_project: + raise NotImplementedError self.filter_projection, _ = self.symbolic_kernels['projection_kernel'] - def _build_diffusion_kernel(self): - if self.should_diffuse: - filter_diffusion, diffusion_kernel_kwds = \ - self.symbolic_kernels['diffusion_kernel'] - self.filter_diffusion = filter_diffusion - def _build_ghost_exchangers(self): def noop(): pass @@ -132,21 +147,24 @@ class OpenClPoissonCurl(SpectralPoissonCurlOperatorBase, OpenClSymbolic): def apply(self, simulation, **kwds): '''Solve the PoissonCurl equation.''' - diffuse=self.should_diffuse - project=self.do_project(simu=simulation) + diffuse = self.should_diffuse + project = self.do_project(simu=simulation) for Ft in self.W_forward_transforms: evt = Ft() - #if diffuse: - #evt = self.filter_diffusion(nu_dt) - #if project: - #evt = self.filter_projection() - #if (diffuse or project): - #for Bt in self.W_backward_transforms: - #evt = Bt() - #evt = self.exchange_W_ghosts() - evt = self.poisson_filter() - for (curl_filter,Bt) in zip(self.curl_filters, self.U_backward_transforms): - evt = curl_filter() + if diffuse: + for Fd in self.diffusion_filters: + evt = Fd() + if project: + evt = self.filter_projection() + if (diffuse or project): + for Bt in self.W_backward_transforms: + evt = Bt() + evt = self.exchange_W_ghosts() + for Fp in self.poisson_filters: + evt = Fp() + for (Fc, Bt) in zip(self.curl_filters, self.U_backward_transforms): + evt = Fc() evt = Bt() evt = self.exchange_U_ghosts() + diff --git a/hysop/operator/base/poisson_curl.py b/hysop/operator/base/poisson_curl.py index 2a9dc65a2..896e4fb87 100644 --- a/hysop/operator/base/poisson_curl.py +++ b/hysop/operator/base/poisson_curl.py @@ -60,9 +60,10 @@ class PoissonCurlOperatorBase(object): # check for diffusion should_diffuse = (diffusion is not None) - if should_diffuse and (dt is None): - msg='Diffusion has been specified but no timestep was given.' - raise RuntimeError(msg) + if should_diffuse: + if (dt is None): + msg='Diffusion has been specified but no timestep was given.' + raise RuntimeError(msg) else: dt = None @@ -105,6 +106,7 @@ class PoissonCurlOperatorBase(object): input_fields = { vorticity: wtopology } output_fields = { velocity: vtopology } if should_diffuse: + assert (dt is not None), 'Diffusion timestep has not been given.' input_params[diffusion.name] = diffusion input_params[dt.name] = dt if (should_diffuse or should_project): @@ -118,7 +120,7 @@ class PoissonCurlOperatorBase(object): self.dim = dim self.should_diffuse = should_diffuse - self.diffusion = diffusion + self.nu = diffusion self.dt = dt self.should_project = should_project -- GitLab