def stress_bc_getter(self, init=False): """ generate code for updating stress field boundary ghost cells - generate inner loop by inserting boundary code (saved in field.bc) - recursive insertion to generate nested loop - loop through all stress fields and sides - if init=True (initialisation), no need to generate code to overwrite Txx, Tyy, Tzz return generated code as string """ result = [] body = [] if self.eval_const: self.create_const_dict() for field in self.sfields: # normal stress, not shear stress normal = field.direction[0] == field.direction[1] for d in range(self.dimension): if init and normal and (not field.direction[0] == d+1): # skip re-calc Txx, Tyy at z plane etc, when initialisation continue for side in range(2): # skip if this boundary calculation is not needed if field.bc[d+1][side] == []: continue if self.omp: result += [cgen.Pragma('omp for schedule(static,1)')] body = [] for d2 in range(self.dimension-1, -1, -1): # loop through other dimensions if not d2 == d: i = self.index[d2] if normal: if field.direction[0] == d+1: # Txx in x plane i0 = 0 i1 = self.dim[d2] else: # Txx in y, z plane i0 = self.margin.value+1 i1 = self.dim[d2]-self.margin.value-1 else: i0 = 0 i1 = self.dim[d2] if not body: # inner loop, populate ghost cell calculation bc_list = self.transform_bc(field, d+1, side) if self.read: body = [cgen.Statement(ccode_eq(self.resolve_media_params(bc)).replace('[_t + 1]', '[_t1]').replace('[_t]', '[_t0]')) for bc in bc_list] else: body = [cgen.Statement(ccode_eq(bc).replace('[_t + 1]', '[_t1]').replace('[_t]', '[_t0]')) for bc in bc_list] body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))] if self.ivdep: body.insert(0, self.compiler._ivdep) if self.simd: body.insert(0, cgen.Pragma('simd')) else: body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))] result += body return cgen.Module(result)
def set_free_surface(self, indices, d, b, side, read=False): """ set free surface boundary condition to boundary d, at index b :param indices: list of indices, e.g. [t,x,y,z] for 3D :param d: direction of the boundary surface normal :param b: location of the boundary (index) side: lower boundary (0) or upper boundary (1) e.g. set_free_surface([t,x,y,z],1,2,0) set y-z plane at x=2 to be lower free surface ghost cells are calculated using reflection of stress fields store the code to populate ghost cells to self.bc """ if d not in self.direction: # e.g. x boundary for field Tyy is not required self.bc[d][side] = '' return idx = list(indices) # ghost cell idx2 = list(indices) # cell inside domain if not self.staggered[d]: # if not staggered, assign T[d]=0, assign T[d-1]=-T[d+1] idx[d] = b idx2[d] = b eq1 = Eq(self[idx]) else: # if staggered, assign T[d-1/2]=T[d+1/2], assign T[d-3/2]=T[d+3/2] idx[d] = b - (1-side) idx2[d] = idx[d] + (-1)**side eq1 = Eq(self[idx], -self[idx2]) idx[d] -= (-1)**side idx2[d] += (-1)**side eq2 = Eq(self[idx], -self[idx2]) self.bc[d][side] = ccode_eq(eq1) + ';\n' + ccode_eq(eq2) + ';\n'
def velocity_bc(self): """ generate code for updating stress field boundary ghost cells - generate inner loop by inserting boundary code (saved in field.bc) - recursive insertion to generate nested loop - loop through all velocity fields and sides return generated code as string """ result = [] if self.eval_const: self.create_const_dict() for d in range(self.dimension): # update the staggered field first # because other fields depends on it sequence = [f for f in self.vfields if f.staggered[d+1]] \ + [f for f in self.vfields if not f.staggered[d+1]] for field in sequence: for side in range(2): # skip if this boundary calculation is not needed if field.bc[d+1][side] == '': continue if self.omp: result += [cgen.Pragma('omp for schedule(static,1)')] body = [] for d2 in range(self.dimension-1, -1, -1): # loop through other dimensions if not d2 == d: i = self.index[d2] i0 = 1 i1 = self.dim[d2]-1 if not body: # inner loop, populate ghost cell calculation # body = field.bc[d+1][side] bc_list = self.transform_bc(field, d+1, side) if self.read: body = [cgen.Statement(ccode_eq(self.resolve_media_params(bc)).replace('[_t + 1]', '[_t1]').replace('[_t]', '[_t0]')) for bc in bc_list] else: body = [cgen.Statement(ccode_eq(bc).replace('[_t + 1]', '[_t1]').replace('[_t]', '[_t0]')) for bc in bc_list] body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))] if self.ivdep: body.insert(0, self.compiler._ivdep) if self.simd: body.insert(0, cgen.Pragma('simd')) else: body = [cgen.For(cgen.InlineInitializer(cgen.Value('int', i), i0), cgen.Line('%s<%s' % (i, i1)), cgen.Line('++%s' % i), cgen.Block(body))] result += body return cgen.Module(result)