def advance(self, write_function, u_np1, u_n, t, dt, n): """Calls preCICE advance function using precice and manages checkpointing. The solution u_n is updated by this function via call-by-reference. The corresponding values for t and n are returned. This means: * either, the checkpoint self._u_cp is assigned to u_n to repeat the iteration, * or u_n+1 is assigned to u_n and the checkpoint is updated correspondingly. :param write_function: a FEniCS function being sent to the other participant as boundary condition at the coupling interface :param u_np1: new value of FEniCS solution u_n+1 at time t_n+1 = t+dt :param u_n: old value of FEniCS solution u_n at time t_n = t; updated via call-by-reference :param t: current time t_n for timestep n :param dt: timestep size dt = t_n+1 - t_n :param n: current timestep :return: return starting time t and timestep n for next FEniCS solver iteration. u_n is updated by advance correspondingly. """ # sample write data at interface x_vert, y_vert = self.extract_coupling_boundary_coordinates() self._write_data = self.convert_fenics_to_precice(write_function, self._mesh_fenics, self._coupling_subdomain) # communication self._interface.write_block_scalar_data(self._write_data_id, self._n_vertices, self._vertex_ids, self._write_data) max_dt = self._interface.advance(dt) self._interface.read_block_scalar_data(self._read_data_id, self._n_vertices, self._vertex_ids, self._read_data) # update boundary condition with read data self._coupling_bc_expression.update_boundary_data(self._read_data, x_vert, y_vert) precice_step_complete = False # checkpointing if self._interface.is_action_required(precice.action_read_iteration_checkpoint()): # continue FEniCS computation from checkpoint u_n.assign(self._u_cp) # set u_n to value of checkpoint t = self._t_cp n = self._n_cp self._interface.fulfilled_action(precice.action_read_iteration_checkpoint()) else: u_n.assign(u_np1) t = new_t = t + dt # todo the variables new_t, new_n could be saved, by just using t and n below, however I think it improved readability. n = new_n = n + 1 if self._interface.is_action_required(precice.action_write_iteration_checkpoint()): # continue FEniCS computation with u_np1 # update checkpoint self._u_cp.assign(u_np1) self._t_cp = new_t self._n_cp = new_n self._interface.fulfilled_action(precice.action_write_iteration_checkpoint()) precice_step_complete = True return t, n, precice_step_complete, max_dt
def _restore_solver_state_from_checkpoint(self, state): """Resets the solver's state to the checkpoint's state. :param state: current state of the FEniCS solver """ logger.debug("Restore solver state") state.update(self._checkpoint.get_state()) self._interface.mark_action_fulfilled(precice.action_read_iteration_checkpoint())
def advance(self, write_function, u_np1, u_n, t, dt, n): """Calls preCICE advance function using precice and manages checkpointing. The solution u_n is updated by this function via call-by-reference. The corresponding values for t and n are returned. This means: * either, the old value of the checkpoint is assigned to u_n to repeat the iteration, * or u_n+1 is assigned to u_n and the checkpoint is updated correspondingly. :param write_function: a FEniCS function being sent to the other participant as boundary condition at the coupling interface :param u_np1: new value of FEniCS solution u_n+1 at time t_n+1 = t+dt :param u_n: old value of FEniCS solution u_n at time t_n = t; updated via call-by-reference :param t: current time t_n for timestep n :param dt: timestep size dt = t_n+1 - t_n :param n: current timestep :return: return starting time t and timestep n for next FEniCS solver iteration. u_n is updated by advance correspondingly. """ state = SolverState(u_n, t, n) # sample write data at interface x_vert, y_vert = self._extract_coupling_boundary_coordinates() self._write_data = self._convert_fenics_to_precice(write_function) # communication self._write_block_data() max_dt = self._interface.advance(dt) self._read_block_data() # update boundary condition with read data if self._has_force_boundary: x_forces, y_forces = self._get_forces_as_point_sources() else: self._coupling_bc_expression.update_boundary_data(self._read_data, x_vert, y_vert) solver_state_has_been_restored = False # checkpointing if self._interface.is_action_required(precice.action_read_iteration_checkpoint()): assert (not self._interface.is_time_window_complete()) # avoids invalid control flow self._restore_solver_state_from_checkpoint(state) solver_state_has_been_restored = True else: self._advance_solver_state(state, u_np1, dt) if self._interface.is_action_required(precice.action_write_iteration_checkpoint()): assert (not solver_state_has_been_restored) # avoids invalid control flow assert (self._interface.is_time_window_complete()) # avoids invalid control flow self._save_solver_state_to_checkpoint(state) precice_step_complete = self._interface.is_time_window_complete() _, t, n = state.get_state() # TODO: this if-else statement smells. if self._has_force_boundary: return t, n, precice_step_complete, max_dt, x_forces, y_forces else: return t, n, precice_step_complete, max_dt
def runPreCICE(self): iteration = 0 previousDisplacements = self.mbd.getDisplacements() while (self.interface.is_coupling_ongoing()): if (self.interface.is_action_required( precice.action_write_iteration_checkpoint())): self.interface.fulfilled_action( precice.action_write_iteration_checkpoint()) if self.dim == 2: f = np.zeros((self.nnodes, 3)) f[:, :self.dim] = np.reshape(self.force, (-1, self.dim)) else: f = np.reshape(self.force, (-1, 3)) self.mbd.setForces(f) if self.mbd.solve(False): break displacements = self.mbd.getDisplacements() relDisplacements = displacements - previousDisplacements self.interface.write_block_vector_data(self.displacementsID, self.nnodes, self.nodeVertexIDs, np.ravel(relDisplacements)) self.interface.advance(self.dt) self.interface.read_block_vector_data(self.forceID, self.nnodes, self.nodeVertexIDs, self.force) if (self.interface.is_action_required( precice.action_read_iteration_checkpoint()) ): # i.e. not yet converged self.interface.fulfilled_action( precice.action_read_iteration_checkpoint()) else: previousDisplacements = displacements.copy() iteration += 1 if self.mbd.solve(True): break if iteration % self.mbd.controlDict['output frequency'] == 0: self.mbd.writeVTK(iteration) self.mbd.finalize()
def advance(self, write_function, read_function, dt, T=None, init_data1=None, init_data2=None, init_data3=None): #def advance(self, write_function, read_function, u_n, t, dt, n): """Calls preCICE advance function using precice and manages checkpointing. The solution u_n is updated by this function via call-by-reference. The corresponding values for t and n are returned. This means: * either, the checkpoint self._u_cp is assigned to u_n to repeat the iteration, * or u_n+1 is assigned to u_n and the checkpoint is updated correspondingly. :param write_function: a FEniCS function being sent to the other participant as boundary condition at the coupling interface :param u_np1: new value of FEniCS solution u_n+1 at time t_n+1 = t+dt :param u_n: old value of FEniCS solution u_n at time t_n = t; updated via call-by-reference :param t: current time t_n for timestep n :param dt: timestep size dt = t_n+1 - t_n :param n: current timestep :return: return starting time t and timestep n for next FEniCS solver iteration. u_n is updated by advance correspondingly. """ precice_step_complete = False fsi_converged = False # sample write data at interface if self._interface.is_action_required( precice.action_write_iteration_checkpoint()): #if T:self.init_T=float(T) #if dt:self.init_dt=float(dt) #self.init_T=float(T) #self.init_dt=float(dt) #if init_data1:self.init_data1=init_data1.copy(True) #if init_data2:self.init_data2=init_data2.copy(True) #if init_data3:self.init_data3=init_data3.copy(True) #fsi_converged=True self._interface.fulfilled_action( precice.action_write_iteration_checkpoint()) self._write_data = self.convert_fenics_to_precice( write_function, self.write_local_dofs) # communication if self.read_n_vertices > 0: if self._write_data_name == "Force" or self._write_data_name == "Displacement": self._interface.write_block_vector_data( self._write_data_id, self.write_n_vertices, self.write_vertex_ids, self._write_data) elif self._write_data_name == "Pressure": self._interface.write_block_scalar_data( self._write_data_id, self.write_n_vertices, self.write_vertex_ids, self._write_data) self._precice_tau = self._interface.advance(float(dt)) dt.assign(min(self._precice_tau, float(dt))) if self.read_n_vertices > 0: self._interface.read_block_vector_data(self._read_data_id, self.read_n_vertices, self.read_vertex_ids, self._read_data) read_function.vector()[self.read_local_dofs] = self._read_data # update boundary condition with read data #self._coupling_bc_expression.update_boundary_data(self._read_data, x_vert, y_vert) # precice_step_complete = False # fsi_converged=False # checkpointing if self._interface.is_action_required( precice.action_read_iteration_checkpoint( )): #not yet converged #if T:self.init_T=float(T) #if dt:self.init_dt=float(dt) #if init_data1:init_data1.vector()[:]=self.init_data1.vector() #if init_data2:init_data2.vector()[:]=self.init_data2.vector() #if init_data3:init_data3.vector()[:]=self.init_data3.vector() #dt.assign(self.init_dt) #T.assign(self.init_T) self._interface.fulfilled_action( precice.action_read_iteration_checkpoint()) else: precice_step_complete = True #if self._interface.is_action_required(precice.action_write_iteration_checkpoint()): #if T:self.init_T=float(T) #if dt:self.init_dt=float(dt) # self.init_T=float(T) # self.init_dt=float(dt) # self.init_data1=init_data1.copy(True) # if init_data2:self.init_data2=init_data2.copy(True) # if init_data3:self.init_data3=init_data3.copy(True) # fsi_converged=True # self._interface.fulfilled_action(precice.action_write_iteration_checkpoint()) #if self._interface.is_action_required(precice.action_write_iteration_checkpoint()): # self._interface.fulfilled_action(precice.action_write_iteration_checkpoint()) return precice_step_complete, self._interface.is_timestep_complete()
def main(inflow: 'inflow velocity' = 10, viscosity: 'kinematic viscosity' = 1.0, density: 'density' = 1.0, theta=0.5, timestepsize=0.01): # mesh and geometry definition grid_x_1 = numpy.linspace(-3, -1, 7) grid_x_1 = grid_x_1[:-1] grid_x_2 = numpy.linspace(-1, -0.3, 8) grid_x_2 = grid_x_2[:-1] grid_x_3 = numpy.linspace(-0.3, 0.3, 13) grid_x_3 = grid_x_3[:-1] grid_x_4 = numpy.linspace(0.3, 1, 8) grid_x_4 = grid_x_4[:-1] grid_x_5 = numpy.linspace(1, 3, 7) grid_x = numpy.concatenate( (grid_x_1, grid_x_2, grid_x_3, grid_x_4, grid_x_5), axis=None) grid_y_1 = numpy.linspace(0, 1.5, 16) grid_y_1 = grid_y_1[:-1] grid_y_2 = numpy.linspace(1.5, 2, 4) grid_y_2 = grid_y_2[:-1] grid_y_3 = numpy.linspace(2, 4, 7) grid_y = numpy.concatenate((grid_y_1, grid_y_2, grid_y_3), axis=None) grid = [grid_x, grid_y] topo, geom = mesh.rectilinear(grid) domain = topo.withboundary(inflow='left', wall='top,bottom', outflow='right') - \ topo[18:20, :10].withboundary(flap='left,right,top') # Nutils namespace ns = function.Namespace() # time approximations # TR interpolation ns._functions['t'] = lambda f: theta * f + (1 - theta) * subs0(f) ns._functions_nargs['t'] = 1 # 1st order FD ns._functions['δt'] = lambda f: (f - subs0(f)) / dt ns._functions_nargs['δt'] = 1 # 2nd order FD ns._functions['tt'] = lambda f: (1.5 * f - 2 * subs0(f) + 0.5 * subs00(f) ) / dt ns._functions_nargs['tt'] = 1 # extrapolation for pressure ns._functions['tp'] = lambda f: (1.5 * f - 0.5 * subs0(f)) ns._functions_nargs['tp'] = 1 ns.nu = viscosity ns.rho = density ns.uin = inflow ns.x0 = geom # reference geometry ns.dbasis = domain.basis('std', degree=1).vector(2) ns.d_i = 'dbasis_ni ?meshdofs_n' ns.umesh_i = 'dbasis_ni (1.5 ?meshdofs_n - 2 ?oldmeshdofs_n + 0.5 ?oldoldmeshdofs_n ) / ?dt' ns.x_i = 'x0_i + d_i' # moving geometry ns.ubasis, ns.pbasis = function.chain([ domain.basis('std', degree=2).vector(2), domain.basis('std', degree=1), ]) ns.F_i = 'ubasis_ni ?F_n' # stress field ns.urel_i = 'ubasis_ni ?lhs_n' # relative velocity ns.u_i = 'umesh_i + urel_i' # total velocity ns.p = 'pbasis_n ?lhs_n' # pressure # initialization of dofs meshdofs = numpy.zeros(len(ns.dbasis)) oldmeshdofs = meshdofs oldoldmeshdofs = meshdofs oldoldoldmeshdofs = meshdofs lhs0 = numpy.zeros(len(ns.ubasis)) # for visualization bezier = domain.sample('bezier', 2) # preCICE setup configFileName = "../precice-config.xml" participantName = "Fluid" solverProcessIndex = 0 solverProcessSize = 1 interface = precice.Interface(participantName, configFileName, solverProcessIndex, solverProcessSize) # define coupling meshes meshName = "Fluid-Mesh" meshID = interface.get_mesh_id(meshName) couplinginterface = domain.boundary['flap'] couplingsample = couplinginterface.sample( 'gauss', degree=2) # mesh located at Gauss points dataIndices = interface.set_mesh_vertices(meshID, couplingsample.eval(ns.x0)) # coupling data writeData = "Force" readData = "Displacement" writedataID = interface.get_data_id(writeData, meshID) readdataID = interface.get_data_id(readData, meshID) # initialize preCICE precice_dt = interface.initialize() dt = min(precice_dt, timestepsize) # boundary conditions for fluid equations sqr = domain.boundary['wall,flap'].integral('urel_k urel_k d:x0' @ ns, degree=4) cons = solver.optimize('lhs', sqr, droptol=1e-15) sqr = domain.boundary['inflow'].integral( '((urel_0 - uin)^2 + urel_1^2) d:x0' @ ns, degree=4) cons = solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons) # weak form fluid equations res = domain.integral('t(ubasis_ni,j (u_i,j + u_j,i) rho nu d:x)' @ ns, degree=4) res += domain.integral('(-ubasis_ni,j p δ_ij + pbasis_n u_k,k) d:x' @ ns, degree=4) res += domain.integral('rho ubasis_ni δt(u_i d:x)' @ ns, degree=4) res += domain.integral('rho ubasis_ni t(u_i,j urel_j d:x)' @ ns, degree=4) # weak form for force computation resF = domain.integral('(ubasis_ni,j (u_i,j + u_j,i) rho nu d:x)' @ ns, degree=4) resF += domain.integral('tp(-ubasis_ni,j p δ_ij d:x)' @ ns, degree=4) resF += domain.integral('pbasis_n u_k,k d:x' @ ns, degree=4) resF += domain.integral('rho ubasis_ni tt(u_i d:x)' @ ns, degree=4) resF += domain.integral('rho ubasis_ni (u_i,j urel_j d:x)' @ ns, degree=4) resF += couplinginterface.sample('gauss', 4).integral('ubasis_ni F_i d:x' @ ns) consF = numpy.isnan( solver.optimize('F', couplinginterface.sample('gauss', 4).integral('F_i F_i' @ ns), droptol=1e-10)) # boundary conditions mesh displacements sqr = domain.boundary['inflow,outflow,wall'].integral('d_i d_i' @ ns, degree=2) meshcons0 = solver.optimize('meshdofs', sqr, droptol=1e-15) # weak form mesh displacements meshsqr = domain.integral('d_i,x0_j d_i,x0_j d:x0' @ ns, degree=2) # better initial guess: start from Stokes solution, comment out for comparison with other solvers #res_stokes = domain.integral('(ubasis_ni,j ((u_i,j + u_j,i) rho nu - p δ_ij) + pbasis_n u_k,k) d:x' @ ns, degree=4) #lhs0 = solver.solve_linear('lhs', res_stokes, constrain=cons, arguments=dict(meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs, dt=dt)) lhs00 = lhs0 timestep = 0 t = 0 while interface.is_coupling_ongoing(): # read displacements from interface if interface.is_read_data_available(): readdata = interface.read_block_vector_data( readdataID, dataIndices) coupledata = couplingsample.asfunction(readdata) sqr = couplingsample.integral(((ns.d - coupledata)**2).sum(0)) meshcons = solver.optimize('meshdofs', sqr, droptol=1e-15, constrain=meshcons0) meshdofs = solver.optimize('meshdofs', meshsqr, constrain=meshcons) # save checkpoint if interface.is_action_required( precice.action_write_iteration_checkpoint()): lhs_checkpoint = lhs0 lhs00_checkpoint = lhs00 t_checkpoint = t timestep_checkpoint = timestep oldmeshdofs_checkpoint = oldmeshdofs oldoldmeshdofs_checkpoint = oldoldmeshdofs oldoldoldmeshdofs_checkpoint = oldoldoldmeshdofs interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) # solve fluid equations lhs1 = solver.newton( 'lhs', res, lhs0=lhs0, constrain=cons, arguments=dict( lhs0=lhs0, dt=dt, meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs)).solve(tol=1e-6) # write forces to interface if interface.is_write_data_required(dt): F = solver.solve_linear('F', resF, constrain=consF, arguments=dict( lhs00=lhs00, lhs0=lhs0, lhs=lhs1, dt=dt, meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs)) # writedata = couplingsample.eval(ns.F, F=F) # for stresses writedata = couplingsample.eval('F_i d:x' @ ns, F=F, meshdofs=meshdofs) * \ numpy.concatenate([p.weights for p in couplingsample.points])[:, numpy.newaxis] interface.write_block_vector_data(writedataID, dataIndices, writedata) # do the coupling precice_dt = interface.advance(dt) dt = min(precice_dt, timestepsize) # advance variables timestep += 1 t += dt lhs00 = lhs0 lhs0 = lhs1 oldoldoldmeshdofs = oldoldmeshdofs oldoldmeshdofs = oldmeshdofs oldmeshdofs = meshdofs # read checkpoint if required if interface.is_action_required( precice.action_read_iteration_checkpoint()): lhs0 = lhs_checkpoint lhs00 = lhs00_checkpoint t = t_checkpoint timestep = timestep_checkpoint oldmeshdofs = oldmeshdofs_checkpoint oldoldmeshdofs = oldoldmeshdofs_checkpoint oldoldoldmeshdofs = oldoldoldmeshdofs_checkpoint interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) if interface.is_time_window_complete(): x, u, p = bezier.eval(['x_i', 'u_i', 'p'] @ ns, lhs=lhs1, meshdofs=meshdofs, oldmeshdofs=oldmeshdofs, oldoldmeshdofs=oldoldmeshdofs, oldoldoldmeshdofs=oldoldoldmeshdofs, dt=dt) with treelog.add(treelog.DataLog()): export.vtk('Fluid_' + str(timestep), bezier.tri, x, u=u, p=p) interface.finalize()
mesh_id = interface.get_mesh_id(mesh_name) dimensions = interface.get_dimensions() vertices = np.zeros((n, dimensions)) vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) dt = interface.initialize() while interface.is_coupling_ongoing(): if interface.is_action_required( precice.action_write_iteration_checkpoint()): print("DUMMY: Writing iteration checkpoint") interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) dt = interface.advance(dt) if interface.is_action_required( precice.action_read_iteration_checkpoint()): print("DUMMY: Reading iteration checkpoint") interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) else: print("DUMMY: Advancing in time") interface.finalize() print("DUMMY: Closing python solver dummy...")
def main(side='Dirichlet'): print("Running nutils") # domain size y_bottom, y_top = 0, 1 x_left, x_right = 0, 2 x_coupling = 1 # x coordinate of coupling interface n = 10 # number of mesh vertices per dimension if side == 'Dirichlet': x_grid = np.linspace(x_left, x_coupling, n) elif side == 'Neumann': x_grid = np.linspace(x_coupling, x_right, n) else: raise Exception('invalid side {!r}'.format(side)) y_grid = np.linspace(y_bottom, y_top, n) # define the Nutils mesh domain, geom = nutils.mesh.rectilinear([x_grid, y_grid]) # Nutils namespace ns = nutils.function.Namespace() ns.x = geom degree = 1 # linear finite elements ns.basis = domain.basis('std', degree=degree) ns.alpha = 3 # parameter of problem ns.beta = 1.3 # parameter of problem ns.u = 'basis_n ?lhs_n' # solution ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative ns.flux = 'basis_n ?fluxdofs_n' # heat flux ns.f = 'beta - 2 - 2 alpha' # rhs ns.uexact = '1 + x_0 x_0 + alpha x_1 x_1 + beta ?t' # analytical solution # define the weak form res0 = domain.integral( '(basis_n dudt - basis_n f + basis_n,i u_,i) d:x' @ ns, degree=degree * 2) # set boundary conditions at non-coupling boundaries # top and bottom boundary are non-coupling for both sides sqr0 = domain.boundary['top'].integral( '(u - 1 - x_0 x_0 - alpha - beta ?t)^2 d:x' @ ns, degree=degree * 2) sqr0 += domain.boundary['bottom'].integral( '(u - 1 - x_0 x_0 - beta ?t)^2 d:x' @ ns, degree=degree * 2) if side == 'Dirichlet': # left boundary is non-coupling sqr0 += domain.boundary['left'].integral( '(u - 1 - alpha x_1 x_1 - beta ?t)^2 d:x' @ ns, degree=degree * 2) elif side == 'Neumann': # right boundary is non-coupling sqr0 += domain.boundary['right'].integral( '(u - 1 - x_0 x_0 - alpha x_1 x_1 - beta ?t)^2 d:x' @ ns, degree=degree * 2) # preCICE setup interface = precice.Interface(side, "../precice-config.xml", 0, 1) # define coupling mesh mesh_name = side + "-Mesh" mesh_id = interface.get_mesh_id(mesh_name) coupling_boundary = domain.boundary['right' if side == 'Dirichlet' else 'left'] coupling_sample = coupling_boundary.sample('gauss', degree=degree * 2) vertices = coupling_sample.eval(ns.x) vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) # coupling data write_data = "Temperature" if side == "Neumann" else "Heat-Flux" read_data = "Heat-Flux" if side == "Neumann" else "Temperature" write_data_id = interface.get_data_id(write_data, mesh_id) read_data_id = interface.get_data_id(read_data, mesh_id) # helper functions to project heat flux to coupling boundary projection_matrix = coupling_boundary.integrate( ns.eval_nm('basis_n basis_m d:x'), degree=degree * 2) projection_cons = np.zeros(res0.shape) projection_cons[projection_matrix.rowsupp(1e-15)] = np.nan def fluxdofs(v): return projection_matrix.solve(v, constrain=projection_cons) # helper data structure to apply heat flux correctly dx_function = 'd:x' @ ns precice_dt = interface.initialize() # write initial data if interface.is_action_required(precice.action_write_initial_data()): write_data = np.zeros(len(vertex_ids)) interface.write_block_scalar_data(write_data_id, vertex_ids, write_data) interface.mark_action_fulfilled(precice.action_write_initial_data()) interface.initialize_data() t = 0 # initial condition sqr = domain.integral('(u - uexact)^2' @ ns, degree=degree * 2) lhs0 = nutils.solver.optimize('lhs', sqr, droptol=1e-15, arguments=dict(t=t)) bezier = domain.sample('bezier', degree * 2) x, u, uexact = bezier.eval(['x_i', 'u', 'uexact'] @ ns, lhs=lhs0, t=t) with treelog.add(treelog.DataLog()): nutils.export.vtk(side + '-0', bezier.tri, x, Temperature=u, reference=uexact) t += precice_dt timestep = 0 dt = 0.1 while interface.is_coupling_ongoing(): # update (time-dependent) boundary condition cons0 = nutils.solver.optimize('lhs', sqr0, droptol=1e-15, arguments=dict(t=t)) # read data from interface if interface.is_read_data_available(): read_data = interface.read_block_scalar_data( read_data_id, vertex_ids) read_function = coupling_sample.asfunction(read_data) if side == 'Dirichlet': sqr = coupling_sample.integral((ns.u - read_function)**2) cons = nutils.solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons0, arguments=dict(t=t)) res = res0 else: cons = cons0 res = res0 + coupling_sample.integral( ns.basis * read_function * dx_function) # save checkpoint if interface.is_action_required( precice.action_write_iteration_checkpoint()): lhs_checkpoint = lhs0 t_checkpoint = t timestep_checkpoint = timestep interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) # potentially adjust non-matching timestep sizes dt = min(dt, precice_dt) # solve nutils timestep lhs = nutils.solver.solve_linear('lhs', res, constrain=cons, arguments=dict(lhs0=lhs0, dt=dt, t=t)) # write data to interface if interface.is_write_data_required(dt): if side == 'Dirichlet': flux_function = res.eval(lhs0=lhs0, lhs=lhs, dt=dt, t=t) write_data = coupling_sample.eval( 'flux' @ ns, fluxdofs=fluxdofs(flux_function)) else: write_data = coupling_sample.eval('u' @ ns, lhs=lhs) interface.write_block_scalar_data(write_data_id, vertex_ids, write_data) # do the coupling precice_dt = interface.advance(dt) # advance variables t += dt timestep += 1 lhs0 = lhs # read checkpoint if required if interface.is_action_required( precice.action_read_iteration_checkpoint()): lhs0 = lhs_checkpoint t = t_checkpoint timestep = timestep_checkpoint interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) else: # go to next timestep bezier = domain.sample('bezier', degree * 2) x, u, uexact = bezier.eval(['x_i', 'u', 'uexact'] @ ns, lhs=lhs, t=t) with treelog.add(treelog.DataLog()): nutils.export.vtk(side + "-" + str(timestep), bezier.tri, x, Temperature=u, reference=uexact) interface.finalize()
def run_simulation(self): iteration = 0 previous_displacement = 0 while self.precice.interface.is_coupling_ongoing(): if self.precice.interface.is_action_required( precice.action_write_iteration_checkpoint()): print("MBDyn Adapter: Writing iteration checkpoint") self.precice.interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) self.precice.read_data() if self.precice.dimensions == 2: force_tensor = np.zeros((self.mbdyn.mesh.number_of_nodes(), 3)) force_tensor[:, :self.precice.dimensions] = np.reshape( self.precice.force, (-1, self.precice.dimensions)) else: force_tensor = np.reshape(self.precice.force, (-1, 3)) max_value_fluid = np.max(np.linalg.norm(force_tensor, axis=1)) if max_value_fluid > 10: force_tensor = force_tensor / max_value_fluid * 0.3 if self._inter_mesh: split = np.split(force_tensor, 2, axis=0) force_tensor = split[0] + split[1] module_logger.debug('dt# = {}'.format(iteration)) force_tensor_norm = np.linalg.norm(force_tensor, axis=1) module_logger.debug( 'min, max, sum forces from precice:\n{}, {}, {}'.format( np.min(force_tensor_norm), np.max(force_tensor_norm), np.sum(force_tensor_norm))) module_logger.debug('forces from precice sample:\n{}'.format( force_tensor[self.mbdyn._debug_samples, :])) if self.mbdyn.load_changed: self.mbdyn.calc_pressure_forces(force_tensor) else: self.mbdyn.set_forces(force_tensor) if self.mbdyn.solve(False): module_logger.debug('Something went wrong!') break if self._inter_mesh: normals = self.mbdyn.get_node_normals() upper_nodes = self.mbdyn.get_nodes() + \ self._inter_mesh_offset * normals lower_nodes = self.mbdyn.get_nodes() - \ self._inter_mesh_offset * normals nodes = np.concatenate((upper_nodes, lower_nodes), axis=0) displacement = nodes - self._inter_mesh_nodes relative_displacement = displacement - previous_displacement else: displacement = self.mbdyn.get_absolute_displacement() relative_displacement = displacement - previous_displacement module_logger.debug( 'min, max relative displacement:\n{}, {}'.format( np.min(relative_displacement), np.max(relative_displacement))) module_logger.debug('relative displacement sample:\n{}'.format( relative_displacement[self.mbdyn._debug_samples, :])) self.precice.write_data(relative_displacement) self.precice.advance_time() if self.precice.interface.is_action_required( precice.action_read_iteration_checkpoint()): print("MBDyn Adapter: Reading iteration checkpoint") self.precice.interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) else: previous_displacement = displacement.copy() iteration = iteration + 1 # self.mbdyn.set_forces(force_tensor) if self.mbdyn.solve(True): break if (iteration % int( self.input.control.entries['output frequency'])) == 0: self.mbdyn.write_output_vtk(iteration) self.mbdyn.finalize() self.precice.interface.finalize()
def main(): print("Running utils") # define the Nutils mesh grid = [ np.linspace(a, b, round((b - a) / size) + 1) for (a, b, size) in [(0, 1, 0.05), (-.25, 0, 0.05)] ] domain, geom = nutils.mesh.rectilinear(grid) # Nutils namespace ns = nutils.function.Namespace() ns.x = geom ns.basis = domain.basis('std', degree=1) # linear finite elements ns.u = 'basis_n ?lhs_n' # solution ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' # time derivative ns.flux = 'basis_n ?fluxdofs_n' # heat flux ns.k = 100 # thermal diffusivity ns.uwall = 310 # wall temperature # define the weak form res = domain.integral('(basis_n dudt + k basis_n,i u_,i) d:x' @ ns, degree=2) # define Dirichlet boundary condition sqr = domain.boundary['bottom'].integral('(u - uwall)^2 d:x' @ ns, degree=2) cons = nutils.solver.optimize('lhs', sqr, droptol=1e-15) # preCICE setup interface = precice.Interface("Solid", "../precice-config.xml", 0, 1) # define coupling mesh mesh_name = "Solid-Mesh" mesh_id = interface.get_mesh_id(mesh_name) coupling_boundary = domain.boundary['top'] coupling_sample = coupling_boundary.sample( 'gauss', degree=2) # mesh vertices at Gauss points vertices = coupling_sample.eval(ns.x) vertex_ids = interface.set_mesh_vertices(mesh_id, vertices) # coupling data flux_id = interface.get_data_id("Heat-Flux", mesh_id) temperature_id = interface.get_data_id("Temperature", mesh_id) # helper functions to project heat flux to coupling boundary projection_matrix = coupling_boundary.integrate( ns.eval_nm('basis_n basis_m d:x'), degree=2) projection_cons = np.zeros(res.shape) projection_cons[projection_matrix.rowsupp(1e-15)] = np.nan def fluxdofs(v): return projection_matrix.solve(v, constrain=projection_cons) precice_dt = interface.initialize() cons0 = cons # to not lose the Dirichlet BC at the bottom lhs0 = np.zeros(res.shape) # solution from previous timestep timestep = 0 dt = 0.01 # set u = uwall as initial condition and visualize sqr = domain.integral('(u - uwall)^2' @ ns, degree=2) lhs0 = nutils.solver.optimize('lhs', sqr) bezier = domain.sample('bezier', 2) x, u = bezier.eval(['x_i', 'u'] @ ns, lhs=lhs0) with treelog.add(treelog.DataLog()): nutils.export.vtk('Solid_0', bezier.tri, x, T=u) while interface.is_coupling_ongoing(): # read temperature from interface if interface.is_read_data_available(): temperature_values = interface.read_block_scalar_data( temperature_id, vertex_ids) temperature_function = coupling_sample.asfunction( temperature_values) sqr = coupling_sample.integral((ns.u - temperature_function)**2) cons = nutils.solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons0) # save checkpoint if interface.is_action_required( precice.action_write_iteration_checkpoint()): lhs_checkpoint = lhs0 timestep_checkpoint = timestep interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) # potentially adjust non-matching timestep sizes dt = min(dt, precice_dt) # solve nutils timestep lhs = nutils.solver.solve_linear('lhs', res, constrain=cons, arguments=dict(lhs0=lhs0, dt=dt)) # write heat fluxes to interface if interface.is_write_data_required(dt): flux_function = res.eval(lhs0=lhs0, lhs=lhs, dt=dt) flux_values = coupling_sample.eval( '-flux' @ ns, fluxdofs=fluxdofs(flux_function)) interface.write_block_scalar_data(flux_id, vertex_ids, flux_values) # do the coupling precice_dt = interface.advance(dt) # advance variables timestep += 1 lhs0 = lhs # read checkpoint if required if interface.is_action_required( precice.action_read_iteration_checkpoint()): lhs0 = lhs_checkpoint timestep = timestep_checkpoint interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) else: # go to next timestep if timestep % 20 == 0: # visualize bezier = domain.sample('bezier', 2) x, u = bezier.eval(['x_i', 'u'] @ ns, lhs=lhs) with treelog.add(treelog.DataLog()): nutils.export.vtk('Solid_' + str(timestep), bezier.tri, x, T=u) interface.finalize()
def readCheckpoint(self): if self.precice.is_action_required( precice.action_read_iteration_checkpoint()): # Do nothing self.precice.fulfilled_action( precice.action_read_iteration_checkpoint())
interface = precice.Interface(participant_name, solver_process_index, solver_process_size) interface.configure(configuration_file_name) mesh_id = interface.get_mesh_id(mesh_name) dimensions = interface.get_dimensions() vertex = np.zeros(dimensions) data_indices = np.zeros(n) interface.set_mesh_vertices(mesh_id, n, vertex, data_indices) dt = interface.initialize() while interface.is_coupling_ongoing(): if interface.is_action_required(precice.action_write_iteration_checkpoint()): print("DUMMY: Writing iteration checkpoint") interface.fulfilled_action(precice.action_write_iteration_checkpoint()) dt = interface.advance(dt) if interface.is_action_required(precice.action_read_iteration_checkpoint()): print("DUMMY: Reading iteration checkpoint") interface.fulfilled_action(precice.action_read_iteration_checkpoint()) else: print("DUMMY: Advancing in time") interface.finalize() print("DUMMY: Closing python solver dummy...")
def main(elemsize: 'mesh width in x and y direction' = 0.05, btype: 'type of basis function (std/spline)' = 'std', degree: 'polynomial degree' = 1, dt=.01): print("Running utils") # the mesh grid = [ numpy.linspace(a, b, round((b - a) / size) + 1) for (a, b, size) in [(0, 1, elemsize), (-.25, 0, elemsize), (0, .05, .05)] ] domain, geom = nutils.mesh.rectilinear(grid, periodic=[2]) # nutils namespace ns = nutils.function.Namespace() ns.x = geom ns.basis = domain.basis(btype, degree=degree) ns.u = 'basis_n ?lhs_n' # solution ns.dudt = 'basis_n (?lhs_n - ?lhs0_n) / ?dt' ns.flux = 'basis_n ?fluxdofs_n' ns.k = 100 # thermal diffusivity ns.uwall = 310 # wall temperature # the weak form res = domain.integral('(basis_n dudt + k basis_n,i u_,i) d:x' @ ns, degree=degree * 2) # Dirichlet boundary condition sqr = domain.boundary['bottom'].integral('(u - uwall)^2 d:x' @ ns, degree=degree * 2) cons = nutils.solver.optimize('lhs', sqr, droptol=1e-15) # preCICE setup configFileName = "../precice-config.xml" participantName = "Nutils" solverProcessIndex = 0 solverProcessSize = 1 interface = precice.Interface(participantName, configFileName, solverProcessIndex, solverProcessSize) # define coupling meshes meshNameGP = "Nutils-Mesh-GP" # Gauss points meshNameCC = "Nutils-Mesh-CC" # cell centers (potentially sub-sampled) meshIDGP = interface.get_mesh_id(meshNameGP) meshIDCC = interface.get_mesh_id(meshNameCC) couplinginterface = domain.boundary['top'] couplingsampleGP = couplinginterface.sample('gauss', degree=degree * 2) couplingsampleCC = couplinginterface.sample( 'uniform', 4) # number of sub-samples for better mapping verticesGP = couplingsampleGP.eval(ns.x) verticesCC = couplingsampleCC.eval(ns.x) dataIndicesGP = interface.set_mesh_vertices(meshIDGP, verticesGP) dataIndicesCC = interface.set_mesh_vertices(meshIDCC, verticesCC) # coupling data writeData = "Heat-Flux" readData = "Temperature" writedataID = interface.get_data_id(writeData, meshIDCC) readdataID = interface.get_data_id(readData, meshIDGP) # heat flux computation projectionmatrix = couplinginterface.integrate( ns.eval_nm('basis_n basis_m d:x'), degree=degree * 2) projectioncons = numpy.zeros(res.shape) projectioncons[projectionmatrix.rowsupp(1e-15)] = numpy.nan fluxdofs = lambda v: projectionmatrix.solve(v, constrain=projectioncons) precice_dt = interface.initialize() cons0 = cons # to not lose the Dirichlet BC at the bottom lhs0 = numpy.zeros(res.shape) timestep = 1 # project initial condition and visualize sqr = domain.integral('(u - uwall)^2' @ ns, degree=degree * 2) lhs0 = nutils.solver.optimize('lhs', sqr) bezier = domain.sample('bezier', 2) x, u = bezier.eval(['x_i', 'u'] @ ns, lhs=lhs0) with treelog.add(treelog.DataLog()): nutils.export.vtk('Solid_0', bezier.tri, x, T=u) while interface.is_coupling_ongoing(): # read temperature from interface if interface.is_read_data_available(): readdata = interface.read_block_scalar_data( readdataID, dataIndicesGP) coupledata = couplingsampleGP.asfunction(readdata) sqr = couplingsampleGP.integral((ns.u - coupledata)**2) cons = nutils.solver.optimize('lhs', sqr, droptol=1e-15, constrain=cons0) # save checkpoint if interface.is_action_required( precice.action_write_iteration_checkpoint()): lhscheckpoint = lhs0 interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) # potentially adjust non-matching timestep sizes dt = min(dt, precice_dt) # solve nutils timestep lhs = nutils.solver.solve_linear('lhs', res, constrain=cons, arguments=dict(lhs0=lhs0, dt=dt)) # write heat fluxes to interface if interface.is_write_data_required(dt): fluxvalues = res.eval(lhs0=lhs0, lhs=lhs, dt=dt) writedata = couplingsampleCC.eval('-flux' @ ns, fluxdofs=fluxdofs(fluxvalues)) interface.write_block_scalar_data(writedataID, dataIndicesCC, writedata) # do the coupling precice_dt = interface.advance(dt) # read checkpoint if required if interface.is_action_required( precice.action_read_iteration_checkpoint()): interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) lhs0 = lhscheckpoint else: # go to next timestep and visualize bezier = domain.sample('bezier', 2) x, u = bezier.eval(['x_i', 'u'] @ ns, lhs=lhs0) with treelog.add(treelog.DataLog()): if timestep % 20 == 0: nutils.export.vtk('Solid_' + str(timestep), bezier.tri, x, T=u) timestep += 1 lhs0 = lhs interface.finalize()
def test_action_read_iteration_checkpoint(self): return_constant = precice.action_read_iteration_checkpoint() dummy_constant = b"dummy_read_iteration" # compare to test/SolverInterface.cpp self.assertEqual(return_constant, dummy_constant)
def runPreCICE(self): iteration = 0 previousDisplacements = self.mbd.getDisplacements() while (self.interface.is_coupling_ongoing()): print("is write") if (self.interface.is_action_required( precice.action_write_iteration_checkpoint())): self.interface.mark_action_fulfilled( precice.action_write_iteration_checkpoint()) # if self.interface.is_read_data_available(): print("reading") self.force = self.interface.read_block_vector_data( self.forceID, self.nodeVertexIDs) # if self.dim == 2: f = np.zeros((self.nnodes, 3)) f[:, :self.dim] = np.reshape(self.force, (-1, self.dim)) else: #import ipdb; ipdb.set_trace() f = np.reshape(self.force, (-1, 3)) self.mbd.setForces(f) if self.mbd.solve(False): break displacements = self.mbd.getDisplacements() #import ipdb; ipdb.set_trace() relDisplacements = displacements - previousDisplacements print("write") # if self.interface.is_write_data_required(self.dt): self.interface.write_block_vector_data( self.displacementsID, self.nodeVertexIDs, np.array(relDisplacements)) # #import ipdb; ipdb.set_trace() '''self.interface.write_block_vector_data(self.displacementsID, self.nodeVertexIDs, np.array(relDisplacements))''' print("pre error") #import ipdb; ipdb.set_trace() self.interface.advance(self.dt) print("post error") print("read") #self.interface.read_block_vector_data(self.forceID, self.nodeVertexIDs) if (self.interface.is_action_required( precice.action_read_iteration_checkpoint()) ): # i.e. not yet self.interface.mark_action_fulfilled( precice.action_read_iteration_checkpoint()) else: previousDisplacements = displacements.copy() iteration += 1 if self.mbd.solve(True): break if iteration % self.mbd.controlDict['output frequency'] == 0: self.mbd.writeVTK(iteration) print("loop") self.mbd.finalize()
def is_action_required_behavior(py_action): if py_action == action_read_iteration_checkpoint(): return False elif py_action == action_write_iteration_checkpoint(): return True
mesh_id = interface.get_mesh_id(mesh_name) forces_id = interface.get_data_id("Forces0", mesh_id) dimensions = interface.get_dimensions() vertex = np.zeros(dimensions) data_indices = np.zeros(n) interface.set_mesh_vertices(mesh_id, n, vertex, data_indices) dt = interface.initialize() while interface.is_coupling_ongoing(): if interface.is_action_required(precice.action_write_iteration_checkpoint()): print("DUMMY: Writing iteration checkpoint") interface.fulfilled_action(precice.action_write_iteration_checkpoint()) interface.write_block_vector_data(forces_id, n, data_indices, np.array((0,0,-1))) # write -1 for y-forces, 0 for x-forces dt = interface.advance(dt) if interface.is_action_required(precice.action_read_iteration_checkpoint()): print("DUMMY: Reading iteration checkpoint") interface.fulfilled_action(precice.action_read_iteration_checkpoint()) else: print("DUMMY: Advancing in time") interface.finalize() print("DUMMY: Closing python solver dummy...")
interface.initialize_data() if interface.is_read_data_available(): pressure = interface.read_block_scalar_data(pressureID, vertexIDs) crossSection0 = crossSection0(pressure.shape[0] - 1) pressure0 = p0 * np.ones_like(pressure) while interface.is_coupling_ongoing(): # When an implicit coupling scheme is used, checkpointing is required if interface.is_action_required(action_write_iteration_checkpoint()): interface.mark_action_fulfilled(action_write_iteration_checkpoint()) crossSectionLength = crossSection0 * ((pressure0 - 2.0 * c_mk**2)**2 / (pressure - 2.0 * c_mk**2)**2) interface.write_block_scalar_data(crossSectionLengthID, vertexIDs, crossSectionLength) precice_dt = interface.advance(precice_dt) pressure = interface.read_block_scalar_data(pressureID, vertexIDs) if interface.is_action_required( action_read_iteration_checkpoint()): # i.e. not yet converged interface.mark_action_fulfilled(action_read_iteration_checkpoint()) else: t += precice_dt print("Exiting SolidSolver") interface.finalize()
time_it = 0 while interface.is_coupling_ongoing(): # When an implicit coupling scheme is used, checkpointing is required if interface.is_action_required(action_write_iteration_checkpoint()): interface.mark_action_fulfilled(action_write_iteration_checkpoint()) velocity, pressure, success = perform_partitioned_implicit_euler_step( velocity_old, pressure_old, crossSectionLength_old, crossSectionLength, dx, precice_dt, velocity_in( t + precice_dt), custom_coupling=True) interface.write_block_scalar_data(pressureID, vertexIDs, pressure) interface.advance(precice_dt) crossSectionLength = interface.read_block_scalar_data( crossSectionLengthID, vertexIDs) # i.e. not yet converged if interface.is_action_required(action_read_iteration_checkpoint()): interface.mark_action_fulfilled(action_read_iteration_checkpoint()) else: # converged, timestep complete t += precice_dt if plotting_mode is config.PlottingModes.VIDEO: tubePlotting.doPlotting( ax, crossSectionLength_old, velocity_old, pressure_old, dx, t) if writeVideoToFile: writer.grab_frame() ax.cla() velocity_old = np.copy(velocity) pressure_old = np.copy(pressure) crossSectionLength_old = np.copy(crossSectionLength) writeOutputToVTK(time_it, "out_fluid_", dx, datanames=["velocity", "pressure", "diameter"], data=[ velocity_old, pressure_old, crossSectionLength_old]) time_it += 1