def transient_pipe_flow_1D( npipes, nx, dof, nphases, pipe_length, initial_time, final_time, initial_time_step, dt_min, dt_max, initial_solution, impl_python=False ): # Time Stepper (TS) for ODE and DAE # DAE - https://en.wikipedia.org/wiki/Differential_algebraic_equation # https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/ ts = PETSc.TS().create() #ts.createPython(MyTS(), comm=PETSc.COMM_SELF) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/DM/index.html pipes = [] for i in range(npipes): boundary_type = PETSc.DMDA.BoundaryType.GHOSTED da = PETSc.DMDA().create([nx], dof=dof, stencil_width=1, stencil_type='star', boundary_type=boundary_type) da.setFromOptions() pipes.append(da) # Create a redundant DM, there is no petsc4py interface (yet) # so we created our own wrapper # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/DM/DMREDUNDANT.html # dmredundant = PETSc.DM().create() # dmredundant.setType(dmredundant.Type.REDUNDANT) # CompositeSimple1D.redundantSetSize(dmredundant, 0, dof) # dmredundant.setDimension(1) # dmredundant.setUp() # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/DM/DMCOMPOSITE.html dm = PETSc.DMComposite().create() for pipe in pipes: dm.addDM(pipe) # dm.addDM(dmredundant) # CompositeSimple1D.compositeSetCoupling(dm) CompositeSimple1D.registerNewSNES() ts.setDM(dm) F = dm.createGlobalVec() if impl_python: α0 = initial_solution.reshape((nx,dof))[:, nphases:-1] pde = Flow(dm, nx, dof, pipe_length, nphases, α0) ts.setIFunction(pde.evalFunction, F) else: # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetIFunction.html assert False, 'C function not implemented yet!' # ts.setIFunction(CompositeSimple1D.formFunction, F, # args=(conductivity, source_term, wall_length, temperature_presc)) snes = ts.getSNES() snes.setUpdate(pde.updateFunction) x = dm.createGlobalVec() x[...] = initial_solution # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetDuration.html ts.setDuration(max_time=final_time, max_steps=None) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetInitialTimeStep.html ts.setInitialTimeStep(initial_time=initial_time, initial_time_step=initial_time_step) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetProblemType.html ts.setProblemType(ts.ProblemType.NONLINEAR) ts.setEquationType(ts.EquationType.IMPLICIT) prev_sol = initial_solution.copy() # restart = PreStep(prev_sol) # ts.setPreStep(restart.prestep) # ts.setPostStep(restart.poststep) options = PETSc.Options() options.setValue('-ts_adapt_dt_min', dt_min) options.setValue('-ts_adapt_dt_max', dt_max) ts.setFromOptions() snes = ts.getSNES() if options.getString('snes_type') in [snes.Type.VINEWTONRSLS, snes.Type.VINEWTONSSLS]: # if True: # snesvi = snes.getCompositeSNES(1) snesvi = snes xl = np.zeros((nx, dof)) xl[:,:nphases] = -100 xl[:,-1] = 0 xl[:, nphases:-1] = 0 xu = np.zeros((nx, dof)) xu[:,:nphases] = 100 xu[:,-1] = 1000 xu[:, nphases:-1] = 1 xlVec = dm.createGlobalVec() xuVec = dm.createGlobalVec() xlVec.setArray(xl.flatten()) xuVec.setArray(xu.flatten()) snesvi.setVariableBounds(xlVec, xuVec) ts.solve(x) # while ts.diverged: # x[...] = prev_sol.copy() # ts.setInitialTimeStep(initial_time=initial_time, initial_time_step=0.5*initial_time_step) # ts.solve(x) final_dt = ts.getTimeStep() return x, final_dt
def transient_heat_transfer_1D( npipes, nx, initial_temperature, temperature_presc, conductivity, source_term, wall_length, final_time, initial_time_step, impl_python=False ): # Time Stepper (TS) for ODE and DAE # DAE - https://en.wikipedia.org/wiki/Differential_algebraic_equation # https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/ ts = PETSc.TS().create() # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/DM/index.html # pipes = [] for i in range(npipes): pipes.append(PETSc.DMDA().create([nx],dof=1, stencil_width=1, stencil_type='star')) # Create a redundant DM, there is no petsc4py interface (yet) # so we created our own wrapper # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/DM/DMREDUNDANT.html dmredundant = PETSc.DM().create() dmredundant.setType(dmredundant.Type.REDUNDANT) HeatTransfer1D.redundantSetSize(dmredundant, 0, 1) dmredundant.setDimension(1) dmredundant.setUp() # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/DM/DMCOMPOSITE.html dm = PETSc.DMComposite().create() for pipe in pipes: dm.addDM(pipe) dm.addDM(dmredundant) HeatTransfer1D.compositeSetCoupling(dm) ts.setDM(dm) F = dm.createGlobalVec() if impl_python: ode = Heat(dm, temperature_presc, conductivity, source_term, wall_length) ts.setIFunction(ode.evalFunction, F) else: # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetIFunction.html ts.setIFunction(HeatTransfer1D.formFunction, F, args=(conductivity, source_term, wall_length, temperature_presc)) x = dm.createGlobalVec() x[...] = initial_temperature #HeatTransfer1D.formInitGuess(x, dm, initial_temperature) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetDuration.html ts.setDuration(max_time=final_time, max_steps=None) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetExactFinalTime.html ts.setExactFinalTime(ts.ExactFinalTimeOption.STEPOVER) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetInitialTimeStep.html ts.setInitialTimeStep(initial_time=0.0, initial_time_step=initial_time_step) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSSetProblemType.html ts.setProblemType(ts.ProblemType.NONLINEAR) # Another way to set the solve type is through PETSc.Options() #ts.setType(ts.Type.CRANK_NICOLSON) #ts.setType(ts.Type.THETA) #ts.setTheta(theta=0.9999) #ts.setType(ts.Type.EIMEX) # http://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/TS/TSEIMEX.html #ts.setType(ts.Type.BDF ) ts.setFromOptions() ts.solve(x) return x