def custom__and__(self, other): if isinstance(other, InvertProductOutputDirichletBC): output = self.copy() mat = to_petsc4py(output) for bc in other.bc_list: constrained_dofs = [bc.function_space().dofmap().local_to_global_index(local_dof_index) for local_dof_index in bc.get_boundary_values().keys()] mat.zeroRowsColumns(constrained_dofs, 0.) return output else: return NotImplemented
def _abs(vector: Vector.Type()): # Note: PETSc offers VecAbs and VecMax, but for symmetry with the matrix case we do the same by hand vec = to_petsc4py(vector) row_start, row_end = vec.getOwnershipRange() i_max = None value_max = None for i in range(row_start, row_end): val = vec.getValue(i) if value_max is None or fabs(val) > fabs(value_max): i_max = i value_max = val assert i_max is not None assert value_max is not None # mpi_comm = vec.comm.tompi4py() (global_value_max, global_i_max) = parallel_max(value_max, (i_max, ), fabs, mpi_comm) return AbsOutput(global_value_max, global_i_max)
def _abs(matrix: Matrix.Type()): # Note: PETSc offers a method MatGetRowMaxAbs, but it is not wrapped in petsc4py. We do the same by hand mat = to_petsc4py(matrix) row_start, row_end = mat.getOwnershipRange() i_max, j_max = None, None value_max = None for i in range(row_start, row_end): cols, vals = mat.getRow(i) for (c, v) in zip(cols, vals): if value_max is None or fabs(v) > fabs(value_max): i_max = i j_max = c value_max = v assert i_max is not None assert j_max is not None assert value_max is not None # mpi_comm = mat.comm.tompi4py() (global_value_max, global_ij_max) = parallel_max(value_max, (i_max, j_max), fabs, mpi_comm) return AbsOutput(global_value_max, global_ij_max)
def _residual_vector_assemble(self, residual_vector_input: GenericVector, petsc_residual: PETSc.Vec): self.residual_vector = PETScVector(petsc_residual) to_petsc4py(residual_vector_input).swap(petsc_residual)
def monitor(self, ts, step, time, solution): """ TSMonitorSet - Sets an ADDITIONAL function that is to be used at every timestep to display the iteration's progress. Logically Collective on TS Input Parameters: + ts - the TS context obtained from TSCreate() . monitor - monitoring routine . mctx - [optional] user-defined context for private data for the monitor routine (use NULL if no context is desired) - monitordestroy - [optional] routine that frees monitor context (may be NULL) Calling sequence of monitor: $ int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx) + ts - the TS context . steps - iteration number (after the final time step the monitor routine may be called with a step of -1, this indicates the solution has been interpolated to this time) . time - current time . u - current iterate - mctx - [optional] monitoring context """ at_final_time_step = (step == -1) while (self.output_t <= time and self.output_t <= self.output_T) or at_final_time_step: self.all_solutions_time.append(self.output_t) if self.time_order == 1: output_solution = self.solution.copy(deepcopy=True) output_solution_petsc = to_petsc4py(output_solution.vector()) ts.interpolate(self.output_t, output_solution_petsc) output_solution_petsc.assemble() output_solution_petsc.ghostUpdate() self.all_solutions.append(output_solution) # Compute time derivative by a simple finite difference output_solution_dot = self.all_solutions[-1].copy(deepcopy=True) if len(self.all_solutions) == 1: # monitor is being called at t = 0. output_solution_dot.vector().zero() else: output_solution_dot.vector().add_local(- self.all_solutions[-2].vector().get_local()) output_solution_dot.vector().apply("add") output_solution_dot.vector()[:] *= 1./self.output_dt self.all_solutions_dot.append(output_solution_dot) if self.output_monitor is not None: self.output_monitor(self.output_t, output_solution, output_solution_dot) else: # ts.interpolate is not yet available for TSALPHA2, assume that no adaptation was carried out (output_solution_petsc, output_solution_dot_petsc) = ts.getSolution2() output_solution_petsc.assemble() output_solution_petsc.ghostUpdate() output_solution = self.solution.copy(deepcopy=True) output_solution.vector().zero() output_solution.vector().add_local(output_solution_petsc.getArray()) output_solution.vector().apply("add") self.all_solutions.append(output_solution) output_solution_dot_petsc.assemble() output_solution_dot_petsc.ghostUpdate() output_solution_dot = self.solution_dot.copy(deepcopy=True) output_solution_dot.vector().zero() output_solution_dot.vector().add_local(output_solution_dot_petsc.getArray()) output_solution_dot.vector().apply("add") self.all_solutions_dot.append(output_solution_dot) # Compute time derivative by a simple finite difference output_solution_dot_dot = self.all_solutions_dot[-1].copy(deepcopy=True) if len(self.all_solutions_dot) == 1: # monitor is being called at t = 0. output_solution_dot_dot.vector().zero() else: output_solution_dot_dot.vector().add_local(- self.all_solutions_dot[-2].vector().get_local()) output_solution_dot_dot.vector().apply("add") output_solution_dot_dot.vector()[:] *= 1./self.output_dt self.all_solutions_dot_dot.append(output_solution_dot_dot) if self.output_monitor is not None: self.output_monitor(self.output_t, output_solution, output_solution_dot, output_solution_dot_dot) self.output_t_prev = self.output_t self.output_t += self.output_dt # Disable final timestep workaround at_final_time_step = False
def _assign(object_to: Vector.Type(), object_from: Vector.Type()): if object_from is not object_to: to_petsc4py(object_from).copy(to_petsc4py(object_to))
def _assign(object_to: Matrix.Type(), object_from: Matrix.Type()): if object_from is not object_to: to_petsc4py(object_from).copy(to_petsc4py(object_to), to_petsc4py(object_to).Structure.SAME_NONZERO_PATTERN)