Exemple #1
0
    def initialize_xdmf_files(self):
        info('  Initializing output files.')
        # for creating paraview scripts
        self.metadata['filename_base'] = self.problem_code + '_' + self.metadata['name']

        # assemble file dictionary
        if self.doSave:
            if self.doSaveDiff:
                self.fileDict.update(self.fileDictDiff)
            if self.metadata['hasTentativeV']:
                self.fileDict.update(self.fileDictTent)
                if self.doSaveDiff:
                    self.fileDict.update(self.fileDictTentDiff)
            if self.metadata['hasTentativeP']:
                self.fileDict.update(self.fileDictTentP)
                if self.doSaveDiff:
                    self.fileDict.update(self.fileDictTentPDiff)
        else:
            self.fileDict = {}
        if self.args.wss != 'none':
            self.fileDict.update(self.fileDictWSSnorm)
            if self.args.wss_method == 'expression':
                self.fileDict.update(self.fileDictWSS)
        if self.args.debug_rot:
            self.fileDict.update(self.fileDictDebugRot)
        # create and setup files
        for key, value in self.fileDict.iteritems():
            value['file'] = XDMFFile(mpi_comm_world(), self.str_dir_name + "/" + self.problem_code + '_' +
                                     self.metadata['name'] + value['name'] + ".xdmf")
            value['file'].parameters['rewrite_function_mesh'] = False  # save mesh only once per file
    def initialize_xdmf_files(self):
        info('  Initializing output files.')
        # for creating paraview scripts
        self.metadata['filename_base'] = self.problem_code + '_' + self.metadata['name']

        # assemble file dictionary
        if self.doSaveDiff:
            self.fileDict.update(self.fileDictDiff)
        if self.metadata['hasTentativeV']:
            self.fileDict.update(self.fileDictTent)
            if self.doSaveDiff:
                self.fileDict.update(self.fileDictTentDiff)
        if self.metadata['hasTentativeP']:
            self.fileDict.update(self.fileDictTentP)
            if self.doSaveDiff:
                self.fileDict.update(self.fileDictTentPDiff)
        if self.args.ldsg:
            self.fileDict.update(self.fileDictLDSG)
        if self.args.wss:
            self.fileDict.update(self.fileDictWSS)
        # create files
        for key, value in self.fileDict.iteritems():
            value['file'] = XDMFFile(mpi_comm_world(), self.str_dir_name + "/" + self.problem_code + '_' +
                                     self.metadata['name'] + value['name'] + ".xdmf")
            value['file'].parameters['rewrite_function_mesh'] = False  # saves lots of space (for use with static mesh)
Exemple #3
0
 def __init__(self):
     info('Initializing Time control')
     # watch is list [total_time, last_start, message_when_measured, count into total time, count into selected time]
     self.watches = {}
     self.last_measurement = 0
     self.measuring = 0
     tic()
 def __init__(self):
     info('Initializing Time control')
     # watch is list [total_time, last_start, message_when_measured, count into total time]
     self.watches = {}
     self.last_measurement = 0
     self.measuring = 0
     tic()
 def end(self, what):
     watch = self.watches[what]
     elapsed = toc() - watch[1]
     watch[0] += elapsed
     if self.watches[what][3]:
         self.measuring -= 1
     info(watch[2]+'. Time: %.4f Total: %.4f' % (elapsed, watch[0]))
     self.last_measurement = toc()
Exemple #6
0
 def end(self, what):
     watch = self.watches[what]
     elapsed = toc() - watch[1]
     watch[0] += elapsed
     if self.watches[what][3]:
         self.measuring -= 1
         self.last_measurement = toc()
     info(watch[2]+'. Time: %.4f Total: %.4f' % (elapsed, watch[0]))
 def averaging_pressure(self, pressure):
     self.tc.start('averageP')
     # averaging pressure (substract average)
     p_average = assemble((1.0/self.volume) * pressure * dx)
     info('Average pressure: %f' % p_average)
     p_average_function = interpolate(Expression("p", p=p_average), self.pSpace)
     # info(p_average_function, pressure, pressure_Q)
     pressure.assign(pressure - p_average_function)
     self.tc.end('averageP')
 def start(self, what):
     if what in self.watches:
         if self.watches[what][3]:
             self.measuring += 1
         self.watches[what][1] = toc()
         from_last = toc()-self.last_measurement
         if self.measuring > 1:
             info('TC (%s): More watches at same time: %d' % (what, self.measuring))
         if from_last > 0.1:
             info('TC (%s): time from last end of measurement: %f' % (what, from_last))
Exemple #9
0
 def start(self, what):
     if what in self.watches:
         if self.watches[what][3]:
             self.measuring += 1
         self.watches[what][1] = toc()
         from_last = toc()-self.last_measurement
         if self.measuring > 1:
             info('TC (%s): More watches at same time: %d' % (what, self.measuring))
         elif from_last > 0.1 and self.watches[what][3]:
             info('TC (%s): time from last end of measurement: %f' % (what, from_last))
Exemple #10
0
 def initialize(self, V, Q, PS, D):
     super(Problem, self).initialize(V, Q, PS, D)
     #info("IC type: " + self.ic)
     info("Velocity scale factor = %4.2f" % self.factor)
     itp = Problem.v_function if self.args.itp == 1 else Problem.v_function_2
     # generate inflow profiles
     for obj in self.inflows:
         obj['velocity_profile'] = Problem.InputVelocityProfile(self.factor*float(obj['reference_coef']),
                                                                obj['center'], obj['normal'], float(obj['radius']),
                                                                itp, degree=2)
Exemple #11
0
 def averaging_pressure(self, pressure):
     """
     :param pressure: average is subtracted from it
     """
     self.tc.start('averageP')
     # averaging pressure (subtract average)
     p_average = assemble((1.0 / self.mesh_volume) * pressure * dx)
     info('Average pressure: %f' % p_average)
     p_average_function = interpolate(Expression("p", p=p_average, degree=1), self.pSpace)
     pressure.assign(pressure - p_average_function)
     self.tc.end('averageP')
Exemple #12
0
 def compute_functionals(self, velocity, pressure, t, step):
     super(Problem, self).compute_functionals(velocity, pressure, t, step)
     out = 0
     for obj in self.outflows:
         outflow = assemble(inner(velocity, self.normal)*obj['measure'])
         out += outflow
         self.listDict['outflow'+obj['number']]['list'].append(outflow)
     self.listDict['outflow']['list'].append(out)
     info('Outflow: %f' % out)
     self.last_status_functional = out/abs(self.last_inflow)
     self.listDict['oiratio']['list'].append(self.last_status_functional)
     info('Outflow/Inflow: %f' % self.last_status_functional)
Exemple #13
0
 def compute_functionals(self, velocity, pressure, t, step):
     super(Problem, self).compute_functionals(velocity, pressure, t, step)
     out = 0
     for obj in self.outflows:
         outflow = assemble(inner(velocity, self.normal) * obj['measure'])
         out += outflow
         self.listDict['outflow' + obj['number']]['list'].append(outflow)
     self.listDict['outflow']['list'].append(out)
     info('Outflow: %f' % out)
     self.last_status_functional = out / abs(self.last_inflow)
     self.listDict['oiratio']['list'].append(self.last_status_functional)
     info('Outflow/Inflow: %f' % self.last_status_functional)
Exemple #14
0
 def initialize(self, V, Q, PS, D):
     super(Problem, self).initialize(V, Q, PS, D)
     #info("IC type: " + self.ic)
     info("Velocity scale factor = %4.2f" % self.factor)
     itp = Problem.v_function if self.args.itp == 1 else Problem.v_function_2
     # generate inflow profiles
     for obj in self.inflows:
         obj['velocity_profile'] = Problem.InputVelocityProfile(
             self.factor * float(obj['reference_coef']),
             obj['center'],
             obj['normal'],
             float(obj['radius']),
             itp,
             degree=2)
Exemple #15
0
  def __init__(self, coarse_mesh, nref, p_coarse, p_fine, sym=False):
    """

    :param dolfin.cpp.mesh.Mesh coarse_mesh:
    :param int nref:
    :param int p_coarse:
    :param int p_fine:
    :param bool sym:
    :return:
    """

    print0("Creating approximation spaces")

    self.V_coarse = FunctionSpace(coarse_mesh, "CG", p_coarse)
    self.ndof_coarse = self.V_coarse.dim()

    refined_mesh = coarse_mesh
    for ref in xrange(nref):
      refined_mesh = refine(refined_mesh)   # creates a new Mesh, initial coarse mesh is unchanged

    self.V_fine = FunctionSpace(refined_mesh, "CG", p_fine)
    self.ndof_fine = self.V_fine.dim()

    H = coarse_mesh.hmax()
    h = refined_mesh.hmax()
    self.alpha = log(H)/log(h)
    self.beta = p_fine + 1

    if comm.rank == 0:
      prop = Table("Approximation properties")
      prop.set("ndof", "coarse", self.ndof_coarse)
      prop.set("ndof", "fine", self.ndof_fine)
      prop.set("h", "coarse", H)
      prop.set("h", "fine", h)

      info(prop)

      print "alpha = {}, beta = {}".format(self.alpha, self.beta)

    self.bc_coarse = None

    self.A_fine = PETScMatrix()
    self.B_fine = PETScMatrix()
    self.A_coarse = PETScMatrix()
    self.B_coarse = PETScMatrix()

    self.sym = sym
    self.switch_gep_matrices = False
    def initialize(self, V, Q, PS, D):
        self.vSpace = V
        self.divSpace = D
        self.pSpace = Q
        self.solutionSpace = V
        self.vFunction = Function(V)
        self.divFunction = Function(D)
        self.pFunction = Function(Q)
        self.volume = assemble(interpolate(Expression("1.0"), Q) * dx)

        if self.doSave:
            # self.pgSpace = VectorFunctionSpace(mesh, "DG", 0)
            # self.pgFunction = Function(self.pgSpace)
            self.initialize_xdmf_files()
        self.stepsInSecond = int(round(1.0 / self.metadata['dt']))
        info('stepsInSecond = %d' % self.stepsInSecond)
Exemple #17
0
    def update_time(self, actual_time, step_number):
        super(Problem, self).update_time(actual_time, step_number)
        if self.actual_time > 0.5 and abs(math.modf(actual_time)[0]) < 0.5*self.metadata['dt']:
            self.second_list.append(int(round(self.actual_time)))

        # Update boundary condition
        self.tc.start('updateBC')
        self.last_inflow = 0
        for obj in self.inflows:
            obj['velocity_profile'].t = actual_time
            obj['velocity_profile'].onset_factor = self.onset_factor
            self.last_inflow += assemble(inner(obj['velocity_profile'], self.normal)*obj['measure'])
        info('Inflow: %f' % self.last_inflow)
        self.listDict['inflow']['list'].append(self.last_inflow)

        self.tc.end('updateBC')
    def update_time(self, actual_time, step_number):
        self.actual_time = actual_time
        self.step_number = step_number
        self.time_list.append(self.actual_time)
        if self.onset < 0.001 or self.actual_time > self.onset:
            self.onset_factor = 1.
        else:
            self.onset_factor = (1. - cos(pi * actual_time / self.onset))*0.5
        info('Onset factor: %f' % self.onset_factor)

        # save only n-th step in first second
        if self.doSave:
            if self.save_nth == 1 or actual_time > (1. - self.metadata['dt']/2.) or self.step_number % self.save_nth == 0:
                self.save_this_step = True
            else:
                self.save_this_step = False
Exemple #19
0
    def update_time(self, actual_time, step_number):
        super(Problem, self).update_time(actual_time, step_number)
        if self.actual_time > 0.5 and abs(
                math.modf(actual_time)[0]) < 0.5 * self.metadata['dt']:
            self.second_list.append(int(round(self.actual_time)))

        # Update boundary condition
        self.tc.start('updateBC')
        self.last_inflow = 0
        for obj in self.inflows:
            obj['velocity_profile'].t = actual_time
            obj['velocity_profile'].onset_factor = self.onset_factor
            self.last_inflow += assemble(
                inner(obj['velocity_profile'], self.normal) * obj['measure'])
        info('Inflow: %f' % self.last_inflow)
        self.listDict['inflow']['list'].append(self.last_inflow)

        self.tc.end('updateBC')
Exemple #20
0
    def compute_functionals(self, velocity, pressure, t, step):
        if self.args.wss == 'all' or \
                (step >= self.stepsInCycle and self.args.wss == 'peak' and
                 (self.distance_from_chosen_steps < 0.5 * self.metadata['dt'])):
            # TODO check if choosing time steps works properly
            # QQ might skip step? change 0.5 to 0.51?
            self.tc.start('WSS')
            begin('WSS (%dth step)' % step)
            if self.args.wss_method == 'expression':
                stress = project(self.nu*2*sym(grad(velocity)), self.T)
                # pressure is not used as it contributes only to the normal component
                stress.set_allow_extrapolation(True)   # need because of some inaccuracies in BoundaryMesh coordinates
                stress_b = interpolate(stress, self.Tb)    # restrict stress to boundary mesh
                # self.fileDict['stress']['file'].write(stress_b, self.actual_time)
                # info('Saved stress tensor')
                info('Computing WSS')
                wss = dot(stress_b, self.nb) - inner(dot(stress_b, self.nb), self.nb)*self.nb
                wss_func = project(wss, self.Vb)
                wss_norm = project(sqrt_ufl(inner(wss, wss)), self.Sb)
                info('Saving WSS')
                self.fileDict['wss']['file'].write(wss_func, self.actual_time)
                self.fileDict['wss_norm']['file'].write(wss_norm, self.actual_time)
            if self.args.wss_method == 'integral':
                wss_norm = Function(self.SDG)
                mS = TestFunction(self.SDG)
                scaling = 1/FacetArea(self.mesh)
                stress = self.nu*2*sym(grad(velocity))
                wss = dot(stress, self.normal) - inner(dot(stress, self.normal), self.normal)*self.normal
                wss_norm_form = scaling*mS*sqrt_ufl(inner(wss, wss))*ds   # ds is integral over exterior facets only
                assemble(wss_norm_form, tensor=wss_norm.vector())
                self.fileDict['wss_norm']['file'].write(wss_norm, self.actual_time)

                # to get vector WSS values:
                # NT this works, but in ParaView for (DG,1)-vector space glyphs are displayed in cell centers
                # wss_vector = []
                # for i in range(3):
                #     wss_component = Function(self.SDG)
                #     wss_vector_form = scaling*wss[i]*mS*ds
                #     assemble(wss_vector_form, tensor=wss_component.vector())
                #     wss_vector.append(wss_component)
                # wss_func = project(as_vector(wss_vector), self.VDG)
                # self.fileDict['wss']['file'].write(wss_func, self.actual_time)
            self.tc.end('WSS')
            end()
Exemple #21
0
    def initialize(self, V, Q, PS, D):
        """
        :param V: velocity space
        :param Q: pressure space
        :param PS: scalar space of same order as V, used for analytic solution generation
        :param D: divergence of velocity space
        """
        self.vSpace = V
        self.divSpace = D
        self.pSpace = Q
        self.solutionSpace = V
        self.vFunction = Function(V)
        self.divFunction = Function(D)
        self.pFunction = Function(Q)

        # self.pgSpace = VectorFunctionSpace(mesh, "DG", 0)    # used to save pressure gradient as vectors
        # self.pgFunction = Function(self.pgSpace)
        self.initialize_xdmf_files()
        self.stepsInCycle = self.cycle_length / self.metadata['dt']
        info('stepsInCycle = %f' % self.stepsInCycle)

        if self.args.wss != 'none':
            self.tc.start('WSSinit')
            if self.args.wss_method == 'expression':
                self.T = TensorFunctionSpace(self.mesh, 'Lagrange', 1)
                info('Generating boundary mesh')
                self.wall_mesh = BoundaryMesh(self.mesh, 'exterior')
                self.wall_mesh_oriented = BoundaryMesh(self.mesh, 'exterior', order=False)
                info('  Boundary mesh geometric dim: %d' % self.wall_mesh.geometry().dim())
                info('  Boundary mesh topologic dim: %d' % self.wall_mesh.topology().dim())
                self.Tb = TensorFunctionSpace(self.wall_mesh, 'Lagrange', 1)
                self.Vb = VectorFunctionSpace(self.wall_mesh, 'Lagrange', 1)
                info('Generating normal to boundary')
                normal_expr = self.NormalExpression(self.wall_mesh_oriented)
                Vn = VectorFunctionSpace(self.wall_mesh, 'DG', 0)
                self.nb = project(normal_expr, Vn)
                self.Sb = FunctionSpace(self.wall_mesh, 'DG', 0)

            if self.args.wss_method == 'integral':
                self.SDG = FunctionSpace(self.mesh, 'DG', 0)

            self.tc.end('WSSinit')
Exemple #22
0
 def compute_err(self, is_tent, velocity, t):
     if self.doErrControl:
         er_list_L2 = self.listDict['u2L2' if is_tent else 'u_L2']['list']
         er_list_H1 = self.listDict['u2H1' if is_tent else 'u_H1']['list']
         self.tc.start('errorV')
         # assemble is faster than errornorm
         errorL2_sq = assemble(inner(velocity - self.solution, velocity - self.solution) * dx)
         errorH1seminorm_sq = assemble(inner(grad(velocity - self.solution), grad(velocity - self.solution)) * dx)
         info('  H1 seminorm error: %f' % sqrt(errorH1seminorm_sq))
         errorL2 = sqrt(errorL2_sq)
         errorH1 = sqrt(errorL2_sq + errorH1seminorm_sq)
         info("  Relative L2 error in velocity = %f" % (errorL2 / self.analytic_v_norm_L2))
         self.last_error = errorH1 / self.analytic_v_norm_H1
         self.last_status_functional = self.last_error
         info("  Relative H1 error in velocity = %f" % self.last_error)
         er_list_L2.append(errorL2)
         er_list_H1.append(errorH1)
         self.tc.end('errorV')
         if self.testErrControl:
             er_list_test_H1 = self.listDict['u2H1test' if is_tent else 'u_H1test']['list']
             er_list_test_L2 = self.listDict['u2L2test' if is_tent else 'u_L2test']['list']
             self.tc.start('errorVtest')
             er_list_test_L2.append(errornorm(velocity, self.solution, norm_type='L2', degree_rise=0))
             er_list_test_H1.append(errornorm(velocity, self.solution, norm_type='H1', degree_rise=0))
             self.tc.end('errorVtest')
         # stopping criteria for detecting diverging solution
         if self.last_error > self.divergence_treshold:
             raise RuntimeError('STOPPED: Failed divergence test!')
Exemple #23
0
    def update_time(self, actual_time, step_number):
        info('GS_UPDATE_TIME t = %f, step %d' % (actual_time, step_number))
        self.actual_time = actual_time
        self.step_number = step_number
        self.time_list.append(self.actual_time)
        if self.onset < 0.001 or self.actual_time > self.onset:  # TODO onset time relative to cycle_length
            self.onset_factor = 1.
        else:
            self.onset_factor = (1. - cos(pi * actual_time / self.onset))*0.5
        info('GS_UPDATE_TIME Onset factor: %f' % self.onset_factor)

        # Manage saving choices for this step
        # save only n-th step in first second

        dec, i = modf(actual_time / self.cycle_length)
        i = int(i)
        info('GS_UPDATE_TIME Cycles done: %d' % i)
        info('GS_UPDATE_TIME Relative part of cycle: %f' % dec)
        dec *= self.cycle_length
        info('GS_UPDATE_TIME Absolute time in  cycle: %f' % dec)
        self.distance_from_chosen_steps = min([abs(dec - d) for d in self.chosen_steps])
        # TODO use self.close_to_chosen_steps
        info('GS_UPDATE_TIME Distance from chosen steps: %f' % self.distance_from_chosen_steps)
        info('GS_UPDATE_TIME Distance threshold: %f' % (0.5 * self.metadata['dt'] + DOLFIN_EPS))

        if self.doSave:
            if self.args.ST == 'min':
                self.save_this_step = (i >= 1 and (self.distance_from_chosen_steps < 0.5 * self.metadata['dt'] + DOLFIN_EPS))
                # QQ might skip step? change 0.5 to 0.51?
            elif self.args.ST == 'peak':
                self.save_this_step = (i >= 1 and 0.1 < dec < 0.20001)  # TODO relative to cycle_length
            elif self.save_nth == 1 or i >= 1 or self.step_number % self.save_nth == 0:
                self.save_this_step = True
            else:
                self.save_this_step = False
            if self.save_this_step:
                info('GS_UPDATE_TIME Chose to save this step: (%f, %d)' % (actual_time, step_number))
Exemple #24
0
 def get_initial_conditions(self, function_list):
     """
     :param function_list: [{'type': 'v'/'p', 'time':-0.1},...]
     :return: velocities and pressures in selected times
     """
     info('get_initial_conditions for this problem was not properly implemented.')
Exemple #25
0
 def get_boundary_conditions(self, use_pressure_BC, v_space, p_space):
     info('get_boundary_conditions() for this problem was not properly implemented.')
Exemple #26
0
    res.set("Exact", "iter_max", 0)

    res.set("SLEPc", "eigenvalue", lam_slepc)
    res.set("SLEPc", "residual",   res_slepc)
    res.set("SLEPc", "time_min",     t_slepc_min)
    res.set("SLEPc", "time_max",     t_slepc_max)
    res.set("SLEPc", "iter_min",    it_slepc_min)
    res.set("SLEPc", "iter_max",    it_slepc_max)

    res.set("EVC", "eigenvalue", lam_evc)
    res.set("EVC", "residual",   res_evc)
    res.set("EVC", "time_min",     t_evc_min)
    res.set("EVC", "time_max",     t_evc_max)
    res.set("EVC", "iter_min",    it_evc_min)
    res.set("EVC", "iter_max",    it_evc_max)
    
    info(res)
    
    print
    print "----------------------------------------------------"
    print "        PROBLEM SPECIFICATION TIMINGS"
    print "____________________________________________________"
    print
    print problem_spec_timings

    print "----------------------------------------------------"
    print "            SOLVER INTERNAL TIMINGS"
    print "____________________________________________________"
    print
    print solver_int_timings
Exemple #27
0
 def report(self, report_file, str_name):
     """
     Writes out complete report. Saves times for the selected watches to csv file (if given).
     """
     total_time = toc()
     info('Total time of %.0f s, (%.2f hours).' % (total_time, total_time/3600.0))
     sorted_by_time = []
     sorted_by_name = []
     sum = 0
     sum_percent = 0
     # sort watches by time measured
     for value in self.watches.itervalues():
         if value[3]:
            sum += value[0]
         if value[4]:
            sum_percent += value[0]
         if not sorted_by_time:
             sorted_by_time.append(value)
         else:
             i = 0
             l = len(sorted_by_time)
             while i < l and value[0]<sorted_by_time[i][0]:
                 i += 1
             sorted_by_time.insert(i, value)
     for value in sorted_by_time:
         if value[0] > 0.000001:
             if value[4]:
                 info('   %-40s: %12.2f s %5.1f %% (%4.1f %%)' % (value[2], value[0], 100.0*value[0]/sum_percent,
                                                                  100.0*value[0]/total_time))
             else:
                 info('   %-40s: %12.2f s         (%4.1f %%)' % (value[2], value[0], 100.0*value[0]/total_time))
         else:
             info('   %-40s: %12.2f s NOT USED' % (value[2], value[0]))
     info('   %-40s: %12.2f s         (%4.1f %%)' % ('Measured', sum, 100.0*sum/total_time))
     info('   %-40s: %12.2f s 100.0 %% (%4.1f %%)' % ('Base for percent values', sum_percent,
                                                      100.0*sum_percent/total_time))
     info('   %-40s: %12.2f s         (%4.1f %%)' % ('Unmeasured', total_time-sum,
                                                     100.0*(total_time-sum)/total_time))
     # report to file
     report_header = ['Name', 'Total time']
     report_data = [str_name, total_time]
     for key in sorted(self.watches.keys()):
         value = self.watches[key]
         if value[4]:
             report_header.append(value[2])
             report_data.append(value[0])
     if report_file is not None:
         writer = csv.writer(report_file, delimiter=';', quotechar='|', quoting=csv.QUOTE_NONE)
         writer.writerow(report_header)
         writer.writerow(report_data)
Exemple #28
0
 def remove_status_file(self):
     if self.MPI_rank == 0:
         try:
             os.remove(self.metadata['name'] + ".run")
         except OSError:
             info('.run file probably not created')
Exemple #29
0
    def __init__(self, args, tc, metadata):
        self.MPI_rank = MPI.rank(mpi_comm_world())

        self.metadata = metadata

        # need to be specified in subclass init before calling this init
        self.problem_code = self.problem_code
        self.metadata['pcode'] = self.problem_code
        self.has_analytic_solution = self.has_analytic_solution
        self.metadata['hasAnalyticSolution'] = self.has_analytic_solution

        self.args = args
        # Time control
        self.tc = tc
        self.tc.init_watch('mesh', 'Imported mesh', True)
        self.tc.init_watch('saveP', 'Saved pressure', True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)
        self.tc.init_watch('averageP', 'Averaged pressure', True)
        self.tc.init_watch('updateBC', 'Updated velocity BC', True, count_to_percent=True)
        self.tc.init_watch('div', 'Computed and saved divergence', True)
        self.tc.init_watch('divNorm', 'Computed norm of divergence', True)
        self.tc.init_watch('WSSinit', 'Initialized mesh for WSS', False)
        self.tc.init_watch('WSS', 'Computed and saved WSS', True)
        self.tc.init_watch('errorV', 'Computed velocity error', True)
        self.tc.init_watch('errorVtest', 'Computed velocity error test', True)

        # If it is sensible (and implemented) to force pressure gradient on outflow boundary
        # 1. set self.outflow_area in initialize
        # 2. implement self.compute_outflow and get_outflow_measures
        self.can_force_outflow = False
        self.outflow_area = None
        self.outflow_measures = []

        # stopping criteria (for relative H1 velocity error norm) (if known)
        self.divergence_treshold = 10

        # used for writing status files .run to monitor progress during computation:
        self.last_status_functional = 0.0
        self.status_functional_str = 'to be defined in Problem class'

        # mesh and function objects
        self.normal = None
        self.mesh = None
        self.facet_function = None
        self.mesh_volume = 0   # must be specified in subclass (needed to compute pressure average)
        self.stepsInCycle = None
        self.vSpace = None
        self.vFunction = None
        self.divSpace = None
        self.divFunction = None
        self.pSpace = None
        # self.pgSpace = None    # NT computing pressure gradient function not used (commented throughout code)
        self.pFunction = None
        # self.pgFunction = None
        self.solutionSpace = None
        self.solution = None

        # time related variables
        self.actual_time = 0.0
        self.cycle_length = 1.0
        self.step_number = 0
        self.chosen_steps = [0.1, 0.125, 0.15, 0.16, 0.165, 0.166, 0.167, 0.17, 0.188, 0.189, 0.2]  # must be specified in subclass
        # 0.166... is peak for real problem, 0.188 is peak for womersley profile
        # TODO chosen_steps should depend on problem (and inflow profile)
        self.distance_from_chosen_steps = 0.0
        self.save_this_step = False
        self.isWholeSecond = None
        self.N1 = None
        self.N0 = None

        # lists used for storing normalization and scaling coefficients
        # (time independent, mainly used in womersley_cylinder)
        self.vel_normalization_factor = []
        self.pg_normalization_factor = []
        self.p_normalization_factor = []
        self.scale_factor = []

        self.analytic_v_norm_L2 = None
        self.analytic_v_norm_H1 = None
        self.analytic_v_norm_H1w = None
        self.last_error = None

        # for WSS generation
        metadata['hasWSS'] = (args.wss != 'none')
        metadata['WSSmethod'] = self.args.wss_method
        self.T = None
        self.Tb = None
        self.wall_mesh = None
        self.wall_mesh_oriented = None
        self.Vb = None
        self.Sb = None
        self.VDG = None
        self.R = None
        self.SDG = None
        self.nb = None

        # dictionaries for output XDMF files
        self.fileDict = {'u': {'name': 'velocity'},
                         'p': {'name': 'pressure'},
                         # 'pg': {'name': 'pressure_grad'},
                         'd': {'name': 'divergence'}}
        self.fileDictTent = {'u2': {'name': 'velocity_tent'},
                             'd2': {'name': 'divergence_tent'}}
        self.fileDictDiff = {'uD': {'name': 'velocity_diff'},
                             'pD': {'name': 'pressure_diff'},
                             'pgD': {'name': 'pressure_grad_diff'}}
        self.fileDictTentDiff = {'u2D': {'name': 'velocity_tent_diff'}}
        self.fileDictTentP = {'p2': {'name': 'pressure_tent'}}
        #                      'pg2': {'name': 'pressure_grad_tent'}}
        self.fileDictTentPDiff = {'p2D': {'name': 'pressure_tent_diff'}}
        #                          'pg2D': {'name': 'pressure_grad_tent_diff'}}
        self.fileDictWSS = {'wss': {'name': 'wss'}, }
        self.fileDictWSSnorm = {'wss_norm': {'name': 'wss_norm'}, }
        self.fileDictDebugRot = {'grad_cor': {'name': 'grad_cor'}, }

        # lists of functionals and other scalar output data
        self.time_list = []  # list of times, when error is  measured (used in report)
        self.second_list = []
        self.listDict = {}  # list of fuctionals
        # dictionary of data lists {list, name, abbreviation, add scaled row to report}
        # normalisation coefficients (time-independent) are added to some lists to be used in normalized data series
        #   coefficients are lists (updated during initialisation, so we cannot use float type)
        #   coefs are equal to average of respective value of analytic solution
        # norm lists (time-dependent normalisation coefficients) are added to some lists to be used in relative data
        #  series (to remove natural pulsation of error due to change in volume flow rate)
        # slist - lists for cycle-averaged values
        # L2(0) means L2 difference of pressures taken with zero average
        self.listDict = {
            'd': {'list': [], 'name': 'corrected velocity L2 divergence', 'abrev': 'DC',
                  'scale': self.scale_factor, 'slist': []},
            'd2': {'list': [], 'name': 'tentative velocity L2 divergence', 'abrev': 'DT',
                   'scale': self.scale_factor, 'slist': []},
            'pg': {'list': [], 'name': 'computed pressure gradient', 'abrev': 'PG', 'scale': self.scale_factor,
                   'norm': self.pg_normalization_factor},
            'pg2': {'list': [], 'name': 'computed pressure tent gradient', 'abrev': 'PTG', 'scale': self.scale_factor,
                    'norm': self.pg_normalization_factor},
        }
        if self.has_analytic_solution:
            self.listDict.update({
                'u_L2': {'list': [], 'name': 'corrected velocity L2 error', 'abrev': 'CE_L2',
                         'scale': self.scale_factor, 'relative': 'av_norm_L2', 'slist': [],
                         'norm': self.vel_normalization_factor},
                'u2L2': {'list': [], 'name': 'tentative velocity L2 error', 'abrev': 'TE_L2',
                         'scale': self.scale_factor, 'relative': 'av_norm_L2', 'slist': [],
                         'norm': self.vel_normalization_factor},
                'u_L2test': {'list': [], 'name': 'test corrected L2 velocity error', 'abrev': 'TestCE_L2',
                             'scale': self.scale_factor},
                'u2L2test': {'list': [], 'name': 'test tentative L2 velocity error', 'abrev': 'TestTE_L2',
                             'scale': self.scale_factor},
                'u_H1': {'list': [], 'name': 'corrected velocity H1 error', 'abrev': 'CE_H1',
                         'scale': self.scale_factor, 'relative': 'av_norm_H1', 'slist': []},
                'u2H1': {'list': [], 'name': 'tentative velocity H1 error', 'abrev': 'TE_H1',
                         'scale': self.scale_factor, 'relative': 'av_norm_H1', 'slist': []},
                'u_H1test': {'list': [], 'name': 'test corrected H1 velocity error', 'abrev': 'TestCE_H1',
                             'scale': self.scale_factor},
                'u2H1test': {'list': [], 'name': 'test tentative H1 velocity error', 'abrev': 'TestTE_H1',
                             'scale': self.scale_factor},
                'apg': {'list': [], 'name': 'analytic pressure gradient', 'abrev': 'APG', 'scale': self.scale_factor,
                        'norm': self.pg_normalization_factor},
                'av_norm_L2': {'list': [], 'name': 'analytic velocity L2 norm', 'abrev': 'AVN_L2'},
                'av_norm_H1': {'list': [], 'name': 'analytic velocity H1 norm', 'abrev': 'AVN_H1'},
                'ap_norm': {'list': [], 'name': 'analytic pressure norm', 'abrev': 'APN'},
                'p': {'list': [], 'name': 'pressure L2(0) error', 'abrev': 'PE', 'scale': self.scale_factor,
                      'slist': [], 'norm': self.p_normalization_factor},
                'pgE': {'list': [], 'name': 'computed pressure gradient error', 'abrev': 'PGE',
                        'scale': self.scale_factor, 'norm': self.pg_normalization_factor, 'slist': []},
                'pgEA': {'list': [], 'name': 'computed absolute pressure gradient error', 'abrev': 'PGEA',
                         'scale': self.scale_factor, 'norm': self.pg_normalization_factor},
                'p2': {'list': [], 'name': 'pressure tent L2(0) error', 'abrev': 'PTE', 'scale': self.scale_factor,
                       'slist': [], 'norm': self.p_normalization_factor},
                'pgE2': {'list': [], 'name': 'computed tent pressure tent gradient error', 'abrev': 'PTGE',
                         'scale': self.scale_factor, 'norm': self.pg_normalization_factor, 'slist': []},
                'pgEA2': {'list': [], 'name': 'computed absolute pressure tent gradient error',
                          'abrev': 'PTGEA', 'scale': self.scale_factor, 'norm': self.pg_normalization_factor}
            })

        # parse arguments
        self.nu = 0.0  # nu should be specified in subclass (fixed or by argument)
        self.onset = args.onset
        self.onset_factor = 0
        # saving options:
        self.doSave = False
        self.saveOnlyVel = False
        self.doSaveDiff = False
        self.save_nth = args.saventh
        option = args.save
        if option == 'doSave' or option == 'diff' or option == 'only_vel':
            self.doSave = True
            if option == 'diff':
                self.doSaveDiff = True
                info('Saving velocity differences.')
            if option == 'only_vel':
                self.saveOnlyVel = True
                info('Saving only velocity profiles.')
            info('Saving solution ON.')
        elif option == 'noSave':
            self.doSave = False
            info('Saving solution OFF.')
        # error control options:
        self.doErrControl = None
        self.testErrControl = False
        if not self.has_analytic_solution:
            self.doErrControl = False
        elif args.error == "noEC":
            self.doErrControl = False
            info("Error control OFF")
        else:
            self.doErrControl = True
            if args.error == "test":
                self.testErrControl = True
                info("Error control in testing mode")
            else:
                info("Error control ON")

        # set directory for results and reports
        self.str_dir_name = "%s_%s_results" % (self.problem_code, metadata['name'])
        self.metadata['dir'] = self.str_dir_name
        # create directory, needed because of using "with open(..." construction later
        if not os.path.exists(self.str_dir_name) and self.MPI_rank == 0:
            os.mkdir(self.str_dir_name)
Exemple #30
0
    def solve(self, problem):
        self.problem = problem
        doSave = problem.doSave
        save_this_step = False
        onlyVel = problem.saveOnlyVel
        dt = self.metadata['dt']

        nu = Constant(self.problem.nu)
        # TODO check proper use of watches
        self.tc.init_watch('init', 'Initialization', True, count_to_percent=False)
        self.tc.init_watch('rhs', 'Assembled right hand side', True, count_to_percent=True)
        self.tc.init_watch('updateBC', 'Updated velocity BC', True, count_to_percent=True)
        self.tc.init_watch('applybc1', 'Applied velocity BC 1st step', True, count_to_percent=True)
        self.tc.init_watch('applybc3', 'Applied velocity BC 3rd step', True, count_to_percent=True)
        self.tc.init_watch('applybcP', 'Applied pressure BC or othogonalized rhs', True, count_to_percent=True)
        self.tc.init_watch('assembleMatrices', 'Initial matrix assembly', False, count_to_percent=True)
        self.tc.init_watch('solve 1', 'Running solver on 1st step', True, count_to_percent=True)
        self.tc.init_watch('solve 2', 'Running solver on 2nd step', True, count_to_percent=True)
        self.tc.init_watch('solve 3', 'Running solver on 3rd step', True, count_to_percent=True)
        self.tc.init_watch('solve 4', 'Running solver on 4th step', True, count_to_percent=True)
        self.tc.init_watch('assembleA1', 'Assembled A1 matrix (without stabiliz.)', True, count_to_percent=True)
        self.tc.init_watch('assembleA1stab', 'Assembled A1 stabilization', True, count_to_percent=True)
        self.tc.init_watch('next', 'Next step assignments', True, count_to_percent=True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)

        self.tc.start('init')

        # Define function spaces (P2-P1)
        mesh = self.problem.mesh
        self.V = VectorFunctionSpace(mesh, "Lagrange", 2)  # velocity
        self.Q = FunctionSpace(mesh, "Lagrange", 1)  # pressure
        self.PS = FunctionSpace(mesh, "Lagrange", 2)  # partial solution (must be same order as V)
        self.D = FunctionSpace(mesh, "Lagrange", 1)   # velocity divergence space
        if self.bc == 'lagrange':
            L = FunctionSpace(mesh, "R", 0)
            QL = self.Q*L

        problem.initialize(self.V, self.Q, self.PS, self.D)

        # Define trial and test functions
        u = TrialFunction(self.V)
        v = TestFunction(self.V)
        if self.bc == 'lagrange':
            (pQL, rQL) = TrialFunction(QL)
            (qQL, lQL) = TestFunction(QL)
        else:
            p = TrialFunction(self.Q)
            q = TestFunction(self.Q)

        n = FacetNormal(mesh)
        I = Identity(u.geometric_dimension())

        # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure
        [u1, u0, p0] = self.problem.get_initial_conditions([{'type': 'v', 'time': -dt},
                                                          {'type': 'v', 'time': 0.0},
                                                          {'type': 'p', 'time': 0.0}])

        if doSave:
            problem.save_vel(False, u0, 0.0)
            problem.save_vel(True, u0, 0.0)

        u_ = Function(self.V)         # current tentative velocity
        u_cor = Function(self.V)         # current corrected velocity
        if self.bc == 'lagrange':
            p_QL = Function(QL)    # current pressure or pressure help function from rotation scheme
            pQ = Function(self.Q)     # auxiliary function for conversion between QL.sub(0) and Q
        else:
            p_ = Function(self.Q)         # current pressure or pressure help function from rotation scheme
        p_mod = Function(self.Q)      # current modified pressure from rotation scheme

        # Define coefficients
        k = Constant(self.metadata['dt'])
        f = Constant((0, 0, 0))

        # Define forms
        # step 1: Tentative velocity, solve to u_
        u_ext = 1.5*u0 - 0.5*u1  # extrapolation for convection term

        # Stabilisation
        h = CellSize(mesh)
        # CBC delta:
        if self.cbcDelta:
            delta = Constant(self.stabCoef)*h/(sqrt(inner(u_ext, u_ext))+h)
        else:
            delta = Constant(self.stabCoef)*h**2/(2*nu*k + k*h*inner(u_ext, u_ext)+h**2)

        if self.use_full_SUPG:
            v1 = v + delta*0.5*k*dot(grad(v), u_ext)
            parameters['form_compiler']['quadrature_degree'] = 6
        else:
            v1 = v

        def nonlinearity(function):
            if self.use_ema:
               return 2*inner(dot(sym(grad(function)), u_ext), v1) * dx + inner(div(function)*u_ext, v1) * dx
                # return 2*inner(dot(sym(grad(function)), u_ext), v) * dx + inner(div(u_ext)*function, v) * dx
                # QQ implement this way?
            else:
                return inner(dot(grad(function), u_ext), v1) * dx

        def diffusion(fce):
            if self.useLaplace:
                return nu*inner(grad(fce), grad(v1)) * dx
            else:
                form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx
                if self.bcv == 'CDN':
                    # IMP will work only if p=0 on output, or we must add term
                    # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer
                    return form
                if self.bcv == 'LAP':
                    return form - inner(nu*dot(grad(fce).T, n), v1)  * problem.get_outflow_measure_form()
                if self.bcv == 'DDN':
                    # IMP will work only if p=0 on output, or we must add term
                    # inner(p0*n, v)*problem.get_outflow_measure_form() to avoid boundary layer
                    return form  # additional term must be added to non-constant part

        def pressure_rhs():
            if self.useLaplace or self.bcv == 'LAP':
                return inner(p0, div(v1)) * dx - inner(p0*n, v1) * problem.get_outflow_measure_form()
                # NT term inner(inner(p, n), v) is 0 when p=0 on outflow
            else:
                return inner(p0, div(v1)) * dx

        a1_const = (1./k)*inner(u, v1)*dx + diffusion(0.5*u)
        a1_change = nonlinearity(0.5*u)
        if self.bcv == 'DDN':
            # IMP Problem: Does not penalize influx for current step, only for the next one
            # IMP this can lead to oscilation: DDN correct next step, but then u_ext is OK so in next step DDN is not used, leading to new influx...
            # u and u_ext cannot be switched, min_value is nonlinear function
            a1_change += -0.5*min_value(Constant(0.), inner(u_ext, n))*inner(u, v1)*problem.get_outflow_measure_form()
            # IMP works only with uflacs compiler

        L1 = (1./k)*inner(u0, v1)*dx - nonlinearity(0.5*u0) - diffusion(0.5*u0) + pressure_rhs()
        if self.bcv == 'DDN':
            L1 += 0.5*min_value(0., inner(u_ext, n))*inner(u0, v1)*problem.get_outflow_measure_form()

        # Non-consistent SUPG stabilisation
        if self.stabilize and not self.use_full_SUPG:
            # a1_stab = delta*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx
            a1_stab = 0.5*delta*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6})
            # NT optional: use Crank Nicolson in stabilisation term: change RHS
            # L1 += -0.5*delta*inner(dot(grad(u0), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6})

        outflow_area = Constant(problem.outflow_area)
        need_outflow = Constant(0.0)
        if self.useRotationScheme:
            # Rotation scheme
            if self.bc == 'lagrange':
                F2 = inner(grad(pQL), grad(qQL))*dx + (1./k)*qQL*div(u_)*dx + pQL*lQL*dx + qQL*rQL*dx
            else:
                F2 = inner(grad(p), grad(q))*dx + (1./k)*q*div(u_)*dx
        else:
            # Projection, solve to p_
            if self.bc == 'lagrange':
                F2 = inner(grad(pQL - p0), grad(qQL))*dx + (1./k)*qQL*div(u_)*dx + pQL*lQL*dx + qQL*rQL*dx
            else:
                if self.forceOutflow and problem.can_force_outflow:
                    info('Forcing outflow.')
                    F2 = inner(grad(p - p0), grad(q))*dx + (1./k)*q*div(u_)*dx
                    for m in problem.get_outflow_measures():
                        F2 += (1./k)*(1./outflow_area)*need_outflow*q*m
                else:
                    F2 = inner(grad(p - p0), grad(q))*dx + (1./k)*q*div(u_)*dx
        a2, L2 = system(F2)

        # step 3: Finalize, solve to u_
        if self.useRotationScheme:
            # Rotation scheme
            if self.bc == 'lagrange':
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_QL.sub(0)), v)*dx
            else:
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_), v)*dx
        else:
            if self.bc == 'lagrange':
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_QL.sub(0) - p0), v)*dx
            else:
                F3 = (1./k)*inner(u - u_, v)*dx + inner(grad(p_ - p0), v)*dx
        a3, L3 = system(F3)

        if self.useRotationScheme:
            # Rotation scheme: modify pressure
            if self.bc == 'lagrange':
                pr = TrialFunction(self.Q)
                qr = TestFunction(self.Q)
                F4 = (pr - p0 - p_QL.sub(0) + nu*div(u_))*qr*dx
            else:
                F4 = (p - p0 - p_ + nu*div(u_))*q*dx
            # TODO zkusit, jestli to nebude rychlejsi? nepocitat soustavu, ale p.assign(...), nutno project(div(u),Q) coz je pocitani podobne soustavy
            # TODO zkusit v project zadat solver_type='lu' >> primy resic by mel byt efektivnejsi
            a4, L4 = system(F4)

        # Assemble matrices
        self.tc.start('assembleMatrices')
        A1_const = assemble(a1_const)  # need to be here, so A1 stays one Python object during repeated assembly
        A1_change = A1_const.copy()  # copy to get matrix with same sparse structure (data will be overwriten)
        if self.stabilize and not self.use_full_SUPG:
            A1_stab = A1_const.copy()  # copy to get matrix with same sparse structure (data will be overwriten)
        A2 = assemble(a2)
        A3 = assemble(a3)
        if self.useRotationScheme:
            A4 = assemble(a4)
        self.tc.end('assembleMatrices')

        if self.solvers == 'direct':
            self.solver_vel_tent = LUSolver('mumps')
            self.solver_vel_cor = LUSolver('mumps')
            self.solver_p = LUSolver('umfpack')
            if self.useRotationScheme:
                self.solver_rot = LUSolver('umfpack')
        else:
            # NT not needed, chosen not to use hypre_parasails
            # if self.prec_v == 'hypre_parasails':  # in FEniCS 1.6.0 inaccessible using KrylovSolver class
            #     self.solver_vel_tent = PETScKrylovSolver('gmres')   # PETSc4py object
            #     self.solver_vel_tent.ksp().getPC().setType('hypre')
            #     PETScOptions.set('pc_hypre_type', 'parasails')
            #     # this is global setting, but preconditioners for pressure solvers are set by their constructors
            # else:
            self.solver_vel_tent = KrylovSolver('gmres', self.prec_v)   # nonsymetric > gmres
            # IMP cannot use 'ilu' in parallel (choose different default option)
            self.solver_vel_cor = KrylovSolver('cg', 'hypre_amg')   # nonsymetric > gmres
            self.solver_p = KrylovSolver('cg', self.prec_p)          # symmetric > CG
            if self.useRotationScheme:
                self.solver_rot = KrylovSolver('cg', self.prec_p)

        solver_options = {'monitor_convergence': True, 'maximum_iterations': 1000, 'nonzero_initial_guess': True}
        # 'nonzero_initial_guess': True   with  solver.solbe(A, u, b) means that
        # Solver will use anything stored in u as an initial guess

        # Get the nullspace if there are no pressure boundary conditions
        foo = Function(self.Q)     # auxiliary vector for setting pressure nullspace
        if self.bc in ['nullspace', 'nullspace_s']:
            null_vec = Vector(foo.vector())
            self.Q.dofmap().set(null_vec, 1.0)
            null_vec *= 1.0/null_vec.norm('l2')
            self.null_space = VectorSpaceBasis([null_vec])
            if self.bc == 'nullspace':
                as_backend_type(A2).set_nullspace(self.null_space)

        # apply global options for Krylov solvers
        self.solver_vel_tent.parameters['relative_tolerance'] = 10 ** (-self.precision_rel_v_tent)
        self.solver_vel_tent.parameters['absolute_tolerance'] = 10 ** (-self.precision_abs_v_tent)
        self.solver_vel_cor.parameters['relative_tolerance'] = 10E-12
        self.solver_vel_cor.parameters['absolute_tolerance'] = 10E-4
        self.solver_p.parameters['relative_tolerance'] = 10**(-self.precision_p)
        self.solver_p.parameters['absolute_tolerance'] = 10E-10
        if self.useRotationScheme:
            self.solver_rot.parameters['relative_tolerance'] = 10**(-self.precision_p)
            self.solver_rot.parameters['absolute_tolerance'] = 10E-10

        if self.solvers == 'krylov':
            for solver in [self.solver_vel_tent, self.solver_vel_cor, self.solver_p, self.solver_rot] if \
                    self.useRotationScheme else [self.solver_vel_tent, self.solver_vel_cor, self.solver_p]:
                for key, value in solver_options.items():
                    try:
                        solver.parameters[key] = value
                    except KeyError:
                        info('Invalid option %s for KrylovSolver' % key)
                        return 1
                solver.parameters['preconditioner']['structure'] = 'same'
                # matrices A2-A4 do not change, so we can reuse preconditioners

        self.solver_vel_tent.parameters['preconditioner']['structure'] = 'same_nonzero_pattern'
        # matrix A1 changes every time step, so change of preconditioner must be allowed

        if self.bc == 'lagrange':
            fa = FunctionAssigner(self.Q, QL.sub(0))

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(self.bc == 'outflow', self.V, self.Q)
        self.tc.end('init')
        # Time-stepping
        info("Running of Incremental pressure correction scheme n. 1")
        ttime = self.metadata['time']
        t = dt
        step = 1
        while t < (ttime + dt/2.0):
            info("t = %f" % t)
            self.problem.update_time(t, step)
            if self.MPI_rank == 0:
                problem.write_status_file(t)

            if doSave:
                save_this_step = problem.save_this_step

            # DDN debug
            # u_ext_in = assemble(inner(u_ext, n)*problem.get_outflow_measure_form())
            # DDN_triggered = assemble(min_value(Constant(0.), inner(u_ext, n))*problem.get_outflow_measure_form())
            # print('DDN: u_ext*n dSout = ', u_ext_in)
            # print('DDN: negative part of u_ext*n dSout = ', DDN_triggered)

            # assemble matrix (it depends on solution)
            self.tc.start('assembleA1')
            assemble(a1_change, tensor=A1_change)  # assembling into existing matrix is faster than assembling new one
            A1 = A1_const.copy()  # we dont want to change A1_const
            A1.axpy(1, A1_change, True)
            self.tc.end('assembleA1')
            self.tc.start('assembleA1stab')
            if self.stabilize and not self.use_full_SUPG:
                assemble(a1_stab, tensor=A1_stab)  # assembling into existing matrix is faster than assembling new one
                A1.axpy(1, A1_stab, True)
            self.tc.end('assembleA1stab')

            # Compute tentative velocity step
            begin("Computing tentative velocity")
            self.tc.start('rhs')
            b = assemble(L1)
            self.tc.end('rhs')
            self.tc.start('applybc1')
            [bc.apply(A1, b) for bc in bcu]
            self.tc.end('applybc1')
            try:
                self.tc.start('solve 1')
                self.solver_vel_tent.solve(A1, u_.vector(), b)
                self.tc.end('solve 1')
                if save_this_step:
                    self.tc.start('saveVel')
                    problem.save_vel(True, u_, t)
                    self.tc.end('saveVel')
                if save_this_step and not onlyVel:
                    problem.save_div(True, u_)
                problem.compute_err(True, u_, t)
                problem.compute_div(True, u_)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            # DDN debug
            # u_ext_in = assemble(inner(u_, n)*problem.get_outflow_measure_form())
            # DDN_triggered = assemble(min_value(Constant(0.), inner(u_, n))*problem.get_outflow_measure_form())
            # print('DDN: u_tent*n dSout = ', u_ext_in)
            # print('DDN: negative part of u_tent*n dSout = ', DDN_triggered)

            if self.useRotationScheme:
                begin("Computing tentative pressure")
            else:
                begin("Computing pressure")
            if self.forceOutflow and problem.can_force_outflow:
                out = problem.compute_outflow(u_)
                info('Tentative outflow: %f' % out)
                n_o = -problem.last_inflow-out
                info('Needed outflow: %f' % n_o)
                need_outflow.assign(n_o)
            self.tc.start('rhs')
            b = assemble(L2)
            self.tc.end('rhs')
            self.tc.start('applybcP')
            [bc.apply(A2, b) for bc in bcp]
            if self.bc in ['nullspace', 'nullspace_s']:
                self.null_space.orthogonalize(b)
            self.tc.end('applybcP')
            try:
                self.tc.start('solve 2')
                if self.bc == 'lagrange':
                    self.solver_p.solve(A2, p_QL.vector(), b)
                else:
                    self.solver_p.solve(A2, p_.vector(), b)
                self.tc.end('solve 2')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if self.useRotationScheme:
                foo = Function(self.Q)
                if self.bc == 'lagrange':
                    fa.assign(pQ, p_QL.sub(0))
                    foo.assign(pQ + p0)
                else:
                    foo.assign(p_+p0)
                problem.averaging_pressure(foo)
                if save_this_step and not onlyVel:
                    problem.save_pressure(True, foo)
            else:
                if self.bc == 'lagrange':
                    fa.assign(pQ, p_QL.sub(0))
                    problem.averaging_pressure(pQ)
                    if save_this_step and not onlyVel:
                        problem.save_pressure(False, pQ)
                else:
                    # we do not want to change p=0 on outflow, it conflicts with do-nothing conditions
                    foo = Function(self.Q)
                    foo.assign(p_)
                    problem.averaging_pressure(foo)
                    if save_this_step and not onlyVel:
                        problem.save_pressure(False, foo)
            end()

            begin("Computing corrected velocity")
            self.tc.start('rhs')
            b = assemble(L3)
            self.tc.end('rhs')
            if not self.B:
                self.tc.start('applybc3')
                [bc.apply(A3, b) for bc in bcu]
                self.tc.end('applybc3')
            try:
                self.tc.start('solve 3')
                self.solver_vel_cor.solve(A3, u_cor.vector(), b)
                self.tc.end('solve 3')
                problem.compute_err(False, u_cor, t)
                problem.compute_div(False, u_cor)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, u_cor, t)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u_cor)
            end()

            # DDN debug
            # u_ext_in = assemble(inner(u_cor, n)*problem.get_outflow_measure_form())
            # DDN_triggered = assemble(min_value(Constant(0.), inner(u_cor, n))*problem.get_outflow_measure_form())
            # print('DDN: u_cor*n dSout = ', u_ext_in)
            # print('DDN: negative part of u_cor*n dSout = ', DDN_triggered)

            if self.useRotationScheme:
                begin("Rotation scheme pressure correction")
                self.tc.start('rhs')
                b = assemble(L4)
                self.tc.end('rhs')
                try:
                    self.tc.start('solve 4')
                    self.solver_rot.solve(A4, p_mod.vector(), b)
                    self.tc.end('solve 4')
                except RuntimeError as inst:
                    problem.report_fail(t)
                    return 1
                problem.averaging_pressure(p_mod)
                if save_this_step and not onlyVel:
                    problem.save_pressure(False, p_mod)
                end()

            # compute functionals (e. g. forces)
            problem.compute_functionals(u_cor,
                                        p_mod if self.useRotationScheme else (pQ if self.bc == 'lagrange' else p_), t)

            # Move to next time step
            self.tc.start('next')
            u1.assign(u0)
            u0.assign(u_cor)
            u_.assign(u_cor)  # use corretced velocity as initial guess in first step

            if self.useRotationScheme:
                p0.assign(p_mod)
            else:
                if self.bc == 'lagrange':
                    p0.assign(pQ)
                else:
                    p0.assign(p_)

            t = round(t + dt, 6)  # round time step to 0.000001
            step += 1
            self.tc.end('next')

        info("Finished: Incremental pressure correction scheme n. 1")
        problem.report()
        return 0
Exemple #31
0
    def __init__(self, args, tc, metadata):
        gs.GeneralSolver.__init__(self, args, tc, metadata)
        self.metadata['hasTentativeV'] = True

        self.solver_vel_tent = None
        self.solver_vel_cor = None
        self.solver_p = None
        self.solver_rot = None
        self.null_space = None

        # input parameters
        self.bc = args.bc
        self.forceOutflow = args.fo
        self.useLaplace = args.laplace
        self.use_full_SUPG = args.cs
        self.bcv = 'NOT' if self.useLaplace else args.bcv
        if self.bcv == 'CDN':
            info('Using classical do nothing condition (Tn=0).')
        if self.bcv == 'DDN':
            info('Using directional do nothing condition (Tn=0.5*negative(u.n)u).')
        if self.bcv == 'LAP':
            info('Using laplace neutral condition (grad(u)n=0).')
        self.stabCoef = args.stab
        self.stabilize = (args.stab > DOLFIN_EPS)
        if self.stabilize:
            if self.use_full_SUPG:
                info('Used consistent streamline-diffusion stabilization with coef.: %f' % args.stab)
            else:
                info('Used non-consistent streamline-diffusion stabilization with coef.: %f' % args.stab)
        else:
            info('No stabilization used.')
        self.solvers = args.solvers
        self.useRotationScheme = args.r
        self.metadata['hasTentativeP'] = self.useRotationScheme

        self.B = args.B
        self.use_ema = args.ema
        self.cbcDelta = args.cbcDelta
        self.prec_v = args.precV
        self.prec_p = args.precP
        self.precision_rel_v_tent = args.prv1
        self.precision_abs_v_tent = args.pav1
        self.precision_p = args.pp
def solve_elasticity(facet_function, E, nu, dt, T_end, output_dir):
    """Solves elasticity problem with Young modulus E, Poisson ration nu,
    timestep dt, until T_end and with output data going to output_dir.
    Geometry is defined by facet_function which also defines rest boundary
    by marker 1 and traction boundary by marker 2."""

    # Get mesh and prepare boundary measure
    mesh = facet_function.mesh()
    gdim = mesh.geometry().dim()
    ds = Measure("ds", subdomain_data=facet_function)

    # Build function space
    U = VectorFunctionSpace(mesh, "Lagrange", 1)
    P = FunctionSpace(mesh, "Lagrange", 1)
    W = MixedFunctionSpace([U, U, P])
    from dolfin.cpp.common import info
    info("Num DOFs %d" % W.dim())

    # Prepare BCs
    bcs = [
        DirichletBC(W.sub(i), gdim * (0.0, ), facet_function, 1)
        for i in [0, 1]
    ]

    # Define constitutive law
    def stress(u, p):
        """Returns 1st Piola-Kirchhoff stress and (local) mass balance
        for given u, p."""
        mu = Constant(E / (2.0 * (1.0 + nu)))
        F = I + grad(u)
        J = det(F)
        B = F * F.T
        T = -p * I + mu * (B - I)  # Cauchy stress
        S = J * T * inv(F).T  # 1st Piola-Kirchhoff stress
        if nu == 0.5:
            # Incompressible
            pp = J - 1.0
        else:
            # Compressible
            lmbd = Constant(E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)))
            pp = 1.0 / lmbd * p + (J * J - 1.0)
        return S, pp

    # Timestepping theta-method parameters
    q = Constant(0.5)
    dt = Constant(dt)

    # Unknowns, values at previous step and test functions
    w = Function(W)
    (u, v, p) = split(w)
    w0 = Function(W)
    (u0, v0, p0) = split(w0)
    (_u, _v, _p) = TestFunctions(W)

    I = Identity(W.mesh().geometry().dim())

    # Balance of momentum
    S, pp = stress(u, p)
    S0, pp0 = stress(u0, p0)
    F1 = (1.0/dt)*inner(u-u0, _u)*dx \
       - ( q*inner(v, _u)*dx + (1.0-q)*inner(v0, _u)*dx )
    F2a = inner(S, grad(_v)) * dx + pp * _p * dx
    F2b = inner(S0, grad(_v)) * dx + pp0 * _p * dx
    F2 = (1.0 / dt) * inner(v - v0, _v) * dx + q * F2a + (1.0 - q) * F2b

    # Traction at boundary
    F = I + grad(u)
    bF_magnitude = Constant(0.0)
    bF_direction = {
        2: Constant((0.0, 1.0)),
        3: Constant((0.0, 0.0, 1.0))
    }[gdim]
    bF = det(F) * dot(inv(F).T, bF_magnitude * bF_direction)
    FF = inner(bF, _v) * ds(2)

    # Whole system and its Jacobian
    F = F1 + F2 + FF
    J = derivative(F, w)

    # Initialize solver
    problem = NonlinearVariationalProblem(F, w, bcs=bcs, J=J)
    solver = NonlinearVariationalSolver(problem)
    solver.parameters['newton_solver']['relative_tolerance'] = 1e-6
    solver.parameters['newton_solver']['linear_solver'] = 'mumps'

    # Extract solution components
    (u, v, p) = w.split()
    u.rename("u", "displacement")
    v.rename("v", "velocity")
    p.rename("p", "pressure")

    # Create files for storing solution
    vfile = File("%s/velo.xdmf" % output_dir)
    ufile = File("%s/disp.xdmf" % output_dir)
    pfile = File("%s/pres.xdmf" % output_dir)

    # Prepare plot window
    plt = plot(u, mode="displacement", interactive=False, wireframe=True)

    # Time-stepping loop
    t = 0.0
    while t <= T_end:
        print "Time: %g" % t
        t += float(dt)

        # Increase traction
        bF_magnitude.assign(100.0 * t)

        # Prepare to solve and solve
        w0.assign(w)
        solver.solve()

        # Store solution to files and plot
        ufile << (u, t)
        vfile << (v, t)
        pfile << (p, t)
        plt.plot(u)
Exemple #33
0
    def solve(self, problem):
        self.problem = problem
        doSave = problem.doSave
        save_this_step = False
        onlyVel = problem.saveOnlyVel
        dt = self.metadata['dt']

        nu = Constant(self.problem.nu)
        self.tc.init_watch('init', 'Initialization', True, count_to_percent=False)
        self.tc.init_watch('solve', 'Running nonlinear solver', True, count_to_percent=True)
        self.tc.init_watch('next', 'Next step assignments', True, count_to_percent=True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)

        self.tc.start('init')

        mesh = self.problem.mesh

        # Define function spaces (P2-P1)
        self.V = VectorFunctionSpace(mesh, "Lagrange", 2)  # velocity
        self.Q = FunctionSpace(mesh, "Lagrange", 1)  # pressure
        self.W = MixedFunctionSpace([self.V, self.Q])
        self.PS = FunctionSpace(mesh, "Lagrange", 2)  # partial solution (must be same order as V)
        self.D = FunctionSpace(mesh, "Lagrange", 1)   # velocity divergence space

        # to assign solution in space W.sub(0) to Function(V) we need FunctionAssigner (cannot be assigned directly)
        fa = FunctionAssigner(self.V, self.W.sub(0))
        velSp = Function(self.V)

        problem.initialize(self.V, self.Q, self.PS, self.D)

        # Define unknown and test function(s) NS
        v, q = TestFunctions(self.W)
        w = Function(self.W)
        dw = TrialFunction(self.W)
        u, p = split(w)

        # Define fields
        n = FacetNormal(mesh)
        I = Identity(u.geometric_dimension())
        theta = 0.5  # Crank-Nicholson
        k = Constant(self.metadata['dt'])

        # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure
        [u0, p0] = self.problem.get_initial_conditions([{'type': 'v', 'time': 0.0}, {'type': 'p', 'time': 0.0}])

        if doSave:
            problem.save_vel(False, u0, 0.0)

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(self.bc == 'outflow', self.W.sub(0), self.W.sub(1))
        # NT bcp is not used

        # Define steady part of the equation
        def T(u):
            return -p * I + 2.0 * nu * sym(grad(u))

        def F(u, v, q):
            return (inner(T(u), grad(v)) - q * div(u)) * dx + inner(grad(u) * u, v) * dx

        # Define variational forms
        F_ns = (inner((u - u0), v) / k) * dx + (1.0 - theta) * F(u0, v, q) + theta * F(u, v, q)
        J_ns = derivative(F_ns, w, dw)
        # J_ns = derivative(F_ns, w)  # did not work

        # NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns, form_compiler_parameters=ffc_options)
        NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns)
        # (var. formulation, unknown, Dir. BC, jacobian, optional)
        NS_solver = NonlinearVariationalSolver(NS_problem)

        prm = NS_solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-08
        prm['newton_solver']['relative_tolerance'] = 1E-08
        # prm['newton_solver']['maximum_iterations'] = 45
        # prm['newton_solver']['relaxation_parameter'] = 1.0
        prm['newton_solver']['linear_solver'] = 'mumps'

        info(NS_solver.parameters, True)

        self.tc.end('init')

        # Time-stepping
        info("Running of direct method")
        ttime = self.metadata['time']
        t = dt
        step = 1
        while t < (ttime + dt/2.0):
            info("t = %f" % t)
            self.problem.update_time(t, step)
            if self.MPI_rank == 0:
                problem.write_status_file(t)

            if doSave:
                save_this_step = problem.save_this_step

            # Compute
            begin("Solving NS ....")
            try:
                self.tc.start('solve')
                NS_solver.solve()
                self.tc.end('solve')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            # Extract solutions:
            (u, p) = w.split()
            fa.assign(velSp, u)
            # we are assigning twice (now and inside save_vel), but it works with one method save_vel for direct and
            #   projection (we could split save_vel to save one assign)

            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, velSp, t)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u)
            problem.compute_err(False, u, t)
            problem.compute_div(False, u)

            # foo = Function(self.Q)
            # foo.assign(p)
            # problem.averaging_pressure(foo)
            # if save_this_step and not onlyVel:
            #     problem.save_pressure(False, foo)

            if save_this_step and not onlyVel:
                problem.save_pressure(False, p)

            # compute functionals (e. g. forces)
            problem.compute_functionals(u, p, t)

            # Move to next time step
            self.tc.start('next')
            u0.assign(velSp)
            t = round(t + dt, 6)  # round time step to 0.000001
            step += 1
            self.tc.end('next')

        info("Finished: direct method")
        problem.report()
        return 0
Exemple #34
0
    def solve(self, problem):
        self.problem = problem
        doSave = problem.doSave
        save_this_step = False
        onlyVel = problem.saveOnlyVel
        dt = self.metadata['dt']

        nu = Constant(self.problem.nu)
        self.tc.init_watch('init',
                           'Initialization',
                           True,
                           count_to_percent=False)
        self.tc.init_watch('rhs',
                           'Assembled right hand side',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('applybc1',
                           'Applied velocity BC 1st step',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('applybc3',
                           'Applied velocity BC 3rd step',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('applybcP',
                           'Applied pressure BC or othogonalized rhs',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('assembleMatrices',
                           'Initial matrix assembly',
                           False,
                           count_to_percent=True)
        self.tc.init_watch('solve 1',
                           'Running solver on 1st step',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('solve 2',
                           'Running solver on 2nd step',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('solve 3',
                           'Running solver on 3rd step',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('solve 4',
                           'Running solver on 4th step',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('assembleA1',
                           'Assembled A1 matrix (without stabiliz.)',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('assembleA1stab',
                           'Assembled A1 stabilization',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('next',
                           'Next step assignments',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)

        self.tc.start('init')

        # Define function spaces (P2-P1)
        mesh = self.problem.mesh
        self.V = VectorFunctionSpace(mesh, "Lagrange", 2)  # velocity
        self.Q = FunctionSpace(mesh, "Lagrange", 1)  # pressure
        self.PS = FunctionSpace(
            mesh, "Lagrange", 2)  # partial solution (must be same order as V)
        self.D = FunctionSpace(mesh, "Lagrange",
                               1)  # velocity divergence space

        problem.initialize(self.V, self.Q, self.PS, self.D)

        # Define trial and test functions
        u = TrialFunction(self.V)
        v = TestFunction(self.V)
        p = TrialFunction(self.Q)
        q = TestFunction(self.Q)

        n = FacetNormal(mesh)
        I = Identity(find_geometric_dimension(u))

        # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure
        [u1, u0, p0] = self.problem.get_initial_conditions([{
            'type': 'v',
            'time': -dt
        }, {
            'type': 'v',
            'time': 0.0
        }, {
            'type': 'p',
            'time': 0.0
        }])

        u_ = Function(self.V)  # current tentative velocity
        u_cor = Function(self.V)  # current corrected velocity
        p_ = Function(
            self.Q
        )  # current pressure or pressure help function from rotation scheme
        p_mod = Function(
            self.Q)  # current modified pressure from rotation scheme

        # Define coefficients
        k = Constant(self.metadata['dt'])
        f = Constant((0, 0, 0))

        # Define forms
        # step 1: Tentative velocity, solve to u_
        u_ext = 1.5 * u0 - 0.5 * u1  # extrapolation for convection term

        # Stabilisation
        h = CellSize(mesh)
        if self.args.cbc_tau:
            # used in Simula cbcflow project
            tau = Constant(self.stabCoef) * h / (sqrt(inner(u_ext, u_ext)) + h)
        else:
            # proposed in R. Codina: On stabilized finite element methods for linear systems of
            # convection-diffusion-reaction equations.
            tau = Constant(self.stabCoef) * k * h**2 / (
                2 * nu * k + k * h * sqrt(DOLFIN_EPS + inner(u_ext, u_ext)) +
                h**2)
            # DOLFIN_EPS is added because of FEniCS bug that inner(u_ext, u_ext) can be negative when u_ext = 0

        if self.use_full_SUPG:
            v1 = v + tau * 0.5 * dot(grad(v), u_ext)
            parameters['form_compiler']['quadrature_degree'] = 6
        else:
            v1 = v

        def nonlinearity(function):
            if self.args.ema:
                return 2 * inner(dot(sym(grad(function)), u_ext), v1
                                 ) * dx + inner(div(function) * u_ext, v1) * dx
            else:
                return inner(dot(grad(function), u_ext), v1) * dx

        def diffusion(fce):
            if self.useLaplace:
                return nu * inner(grad(fce), grad(v1)) * dx
            else:
                form = inner(nu * 2 * sym(grad(fce)), sym(grad(v1))) * dx
                if self.bcv == 'CDN':
                    return form
                if self.bcv == 'LAP':
                    return form - inner(nu * dot(grad(fce).T, n), v1
                                        ) * problem.get_outflow_measure_form()
                if self.bcv == 'DDN':
                    return form  # additional term must be added to non-constant part

        def pressure_rhs():
            if self.args.bc == 'outflow':
                return inner(p0, div(v1)) * dx
            else:
                return inner(p0, div(v1)) * dx - inner(
                    p0 * n, v1) * problem.get_outflow_measure_form()

        a1_const = (1. / k) * inner(u, v1) * dx + diffusion(0.5 * u)
        a1_change = nonlinearity(0.5 * u)
        if self.bcv == 'DDN':
            # does not penalize influx for current step, only for the next one
            # this can lead to oscilation:
            # DDN correct next step, but then u_ext is OK so in next step DDN is not used, leading to new influx...
            # u and u_ext cannot be switched, min_value is nonlinear function
            a1_change += -0.5 * min_value(Constant(0.), inner(
                u_ext, n)) * inner(u, v1) * problem.get_outflow_measure_form()
            # NT works only with uflacs compiler

        L1 = (1. / k) * inner(u0, v1) * dx - nonlinearity(
            0.5 * u0) - diffusion(0.5 * u0) + pressure_rhs()
        if self.bcv == 'DDN':
            L1 += 0.5 * min_value(0., inner(u_ext, n)) * inner(
                u0, v1) * problem.get_outflow_measure_form()

        # Non-consistent SUPG stabilisation
        if self.stabilize and not self.use_full_SUPG:
            # a1_stab = tau*inner(dot(grad(u), u_ext), dot(grad(v), u_ext))*dx
            a1_stab = 0.5 * tau * inner(dot(grad(u), u_ext), dot(
                grad(v), u_ext)) * dx(None, {'quadrature_degree': 6})
            # optional: to use Crank Nicolson in stabilisation term following change of RHS is needed:
            # L1 += -0.5*tau*inner(dot(grad(u0), u_ext), dot(grad(v), u_ext))*dx(None, {'quadrature_degree': 6})

        outflow_area = Constant(problem.outflow_area)
        need_outflow = Constant(0.0)
        if self.useRotationScheme:
            # Rotation scheme
            F2 = inner(grad(p), grad(q)) * dx + (1. / k) * q * div(u_) * dx
        else:
            # Projection, solve to p_
            if self.forceOutflow and problem.can_force_outflow:
                info('Forcing outflow.')
                F2 = inner(grad(p - p0),
                           grad(q)) * dx + (1. / k) * q * div(u_) * dx
                for m in problem.get_outflow_measures():
                    F2 += (1. / k) * (1. / outflow_area) * need_outflow * q * m
            else:
                F2 = inner(grad(p - p0),
                           grad(q)) * dx + (1. / k) * q * div(u_) * dx
        a2, L2 = system(F2)

        # step 3: Finalize, solve to u_
        if self.useRotationScheme:
            # Rotation scheme
            F3 = (1. / k) * inner(u - u_, v) * dx + inner(grad(p_), v) * dx
        else:
            F3 = (1. / k) * inner(u - u_, v) * dx + inner(grad(p_ - p0),
                                                          v) * dx
        a3, L3 = system(F3)

        if self.useRotationScheme:
            # Rotation scheme: modify pressure
            F4 = (p - p0 - p_ + nu * div(u_)) * q * dx
            a4, L4 = system(F4)

        # Assemble matrices
        self.tc.start('assembleMatrices')
        A1_const = assemble(
            a1_const
        )  # must be here, so A1 stays one Python object during repeated assembly
        A1_change = A1_const.copy(
        )  # copy to get matrix with same sparse structure (data will be overwritten)
        if self.stabilize and not self.use_full_SUPG:
            A1_stab = A1_const.copy(
            )  # copy to get matrix with same sparse structure (data will be overwritten)
        A2 = assemble(a2)
        A3 = assemble(a3)
        if self.useRotationScheme:
            A4 = assemble(a4)
        self.tc.end('assembleMatrices')

        if self.solvers == 'direct':
            self.solver_vel_tent = LUSolver('mumps')
            self.solver_vel_cor = LUSolver('mumps')
            self.solver_p = LUSolver('mumps')
            if self.useRotationScheme:
                self.solver_rot = LUSolver('mumps')
        else:
            # NT 2016-1  KrylovSolver >> PETScKrylovSolver

            # not needed, chosen not to use hypre_parasails:
            # if self.prec_v == 'hypre_parasails':  # in FEniCS 1.6.0 inaccessible using KrylovSolver class
            #     self.solver_vel_tent = PETScKrylovSolver('gmres')   # PETSc4py object
            #     self.solver_vel_tent.ksp().getPC().setType('hypre')
            #     PETScOptions.set('pc_hypre_type', 'parasails')
            #     # this is global setting, but preconditioners for pressure solvers are set by their constructors
            # else:
            self.solver_vel_tent = PETScKrylovSolver(
                'gmres', self.args.precV)  # nonsymetric > gmres
            # cannot use 'ilu' in parallel
            self.solver_vel_cor = PETScKrylovSolver('cg', self.args.precVC)
            self.solver_p = PETScKrylovSolver(
                self.args.solP,
                self.args.precP)  # almost (up to BC) symmetric > CG
            if self.useRotationScheme:
                self.solver_rot = PETScKrylovSolver('cg', 'hypre_amg')

        # setup Krylov solvers
        if self.solvers == 'krylov':
            # Get the nullspace if there are no pressure boundary conditions
            foo = Function(
                self.Q)  # auxiliary vector for setting pressure nullspace
            if self.args.bc == 'nullspace':
                null_vec = Vector(foo.vector())
                self.Q.dofmap().set(null_vec, 1.0)
                null_vec *= 1.0 / null_vec.norm('l2')
                self.null_space = VectorSpaceBasis([null_vec])
                as_backend_type(A2).set_nullspace(self.null_space)

            # apply global options for Krylov solvers
            solver_options = {
                'monitor_convergence': True,
                'maximum_iterations': 10000,
                'nonzero_initial_guess': True
            }
            # 'nonzero_initial_guess': True   with  solver.solve(A, u, b) means that
            # Solver will use anything stored in u as an initial guess
            for solver in [self.solver_vel_tent, self.solver_vel_cor, self.solver_rot, self.solver_p] if \
                    self.useRotationScheme else [self.solver_vel_tent, self.solver_vel_cor, self.solver_p]:
                for key, value in solver_options.items():
                    try:
                        solver.parameters[key] = value
                    except KeyError:
                        info('Invalid option %s for KrylovSolver' % key)
                        return 1

            if self.args.solP == 'richardson':
                self.solver_p.parameters['monitor_convergence'] = False

            self.solver_vel_tent.parameters['relative_tolerance'] = 10**(
                -self.args.prv1)
            self.solver_vel_tent.parameters['absolute_tolerance'] = 10**(
                -self.args.pav1)
            self.solver_vel_cor.parameters['relative_tolerance'] = 10E-12
            self.solver_vel_cor.parameters['absolute_tolerance'] = 10E-4
            self.solver_p.parameters['relative_tolerance'] = 10**(
                -self.args.prp)
            self.solver_p.parameters['absolute_tolerance'] = 10**(
                -self.args.pap)
            if self.useRotationScheme:
                self.solver_rot.parameters['relative_tolerance'] = 10E-10
                self.solver_rot.parameters['absolute_tolerance'] = 10E-10

            if self.args.Vrestart > 0:
                self.solver_vel_tent.parameters['gmres'][
                    'restart'] = self.args.Vrestart

            if self.args.solP == 'gmres' and self.args.Prestart > 0:
                self.solver_p.parameters['gmres'][
                    'restart'] = self.args.Prestart

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(self.args.bc == 'outflow',
                                                   self.V, self.Q)
        self.tc.end('init')
        # Time-stepping
        info("Running of Incremental pressure correction scheme n. 1")
        ttime = self.metadata['time']
        t = dt
        step = 1

        # debug function
        if problem.args.debug_rot:
            plot_cor_v = Function(self.V)

        while t < (ttime + dt / 2.0):
            self.problem.update_time(t, step)
            if self.MPI_rank == 0:
                problem.write_status_file(t)

            if doSave:
                save_this_step = problem.save_this_step

            # assemble matrix (it depends on solution)
            self.tc.start('assembleA1')
            assemble(
                a1_change, tensor=A1_change
            )  # assembling into existing matrix is faster than assembling new one
            A1 = A1_const.copy()  # we dont want to change A1_const
            A1.axpy(1, A1_change, True)
            self.tc.end('assembleA1')
            self.tc.start('assembleA1stab')
            if self.stabilize and not self.use_full_SUPG:
                assemble(
                    a1_stab, tensor=A1_stab
                )  # assembling into existing matrix is faster than assembling new one
                A1.axpy(1, A1_stab, True)
            self.tc.end('assembleA1stab')

            # Compute tentative velocity step
            begin("Computing tentative velocity")
            self.tc.start('rhs')
            b = assemble(L1)
            self.tc.end('rhs')
            self.tc.start('applybc1')
            [bc.apply(A1, b) for bc in bcu]
            self.tc.end('applybc1')
            try:
                self.tc.start('solve 1')
                self.solver_vel_tent.solve(A1, u_.vector(), b)
                self.tc.end('solve 1')
                if save_this_step:
                    self.tc.start('saveVel')
                    problem.save_vel(True, u_)
                    self.tc.end('saveVel')
                if save_this_step and not onlyVel:
                    problem.save_div(True, u_)
                problem.compute_err(True, u_, t)
                problem.compute_div(True, u_)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            if self.useRotationScheme:
                begin("Computing tentative pressure")
            else:
                begin("Computing pressure")
            if self.forceOutflow and problem.can_force_outflow:
                out = problem.compute_outflow(u_)
                info('Tentative outflow: %f' % out)
                n_o = -problem.last_inflow - out
                info('Needed outflow: %f' % n_o)
                need_outflow.assign(n_o)
            self.tc.start('rhs')
            b = assemble(L2)
            self.tc.end('rhs')
            self.tc.start('applybcP')
            [bc.apply(A2, b) for bc in bcp]
            if self.args.bc == 'nullspace':
                self.null_space.orthogonalize(b)
            self.tc.end('applybcP')
            try:
                self.tc.start('solve 2')
                self.solver_p.solve(A2, p_.vector(), b)
                self.tc.end('solve 2')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if self.useRotationScheme:
                foo = Function(self.Q)
                foo.assign(p_ + p0)
                if save_this_step and not onlyVel:
                    problem.averaging_pressure(foo)
                    problem.save_pressure(True, foo)
            else:
                foo = Function(self.Q)
                foo.assign(p_)  # we do not want to change p_ by averaging
                if save_this_step and not onlyVel:
                    problem.averaging_pressure(foo)
                    problem.save_pressure(False, foo)
            end()

            begin("Computing corrected velocity")
            self.tc.start('rhs')
            b = assemble(L3)
            self.tc.end('rhs')
            if not self.args.B:
                self.tc.start('applybc3')
                [bc.apply(A3, b) for bc in bcu]
                self.tc.end('applybc3')
            try:
                self.tc.start('solve 3')
                self.solver_vel_cor.solve(A3, u_cor.vector(), b)
                self.tc.end('solve 3')
                problem.compute_err(False, u_cor, t)
                problem.compute_div(False, u_cor)
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, u_cor)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u_cor)
            end()

            if self.useRotationScheme:
                begin("Rotation scheme pressure correction")
                self.tc.start('rhs')
                b = assemble(L4)
                self.tc.end('rhs')
                try:
                    self.tc.start('solve 4')
                    self.solver_rot.solve(A4, p_mod.vector(), b)
                    self.tc.end('solve 4')
                except RuntimeError as inst:
                    problem.report_fail(t)
                    return 1
                if save_this_step and not onlyVel:
                    problem.averaging_pressure(p_mod)
                    problem.save_pressure(False, p_mod)
                end()

                if problem.args.debug_rot:
                    # save applied pressure correction (expressed as a term added to RHS of next tentative vel. step)
                    # see comment next to argument definition
                    plot_cor_v.assign(project(k * grad(nu * div(u_)), self.V))
                    problem.fileDict['grad_cor']['file'].write(plot_cor_v, t)

            # compute functionals (e. g. forces)
            problem.compute_functionals(
                u_cor, p_mod if self.useRotationScheme else p_, t, step)

            # Move to next time step
            self.tc.start('next')
            u1.assign(u0)
            u0.assign(u_cor)
            u_.assign(
                u_cor)  # use corrected velocity as initial guess in first step

            if self.useRotationScheme:
                p0.assign(p_mod)
            else:
                p0.assign(p_)

            t = round(t + dt, 6)  # round time step to 0.000001
            step += 1
            self.tc.end('next')

        info("Finished: Incremental pressure correction scheme n. 1")
        problem.report()
        return 0
Exemple #35
0
 def get_outflow_measures(self):
     """
     return list of Measure objects for outflow boundary parts
     must be overridden in Problem before use (if needed)
     """
     info('Integration over outflow for this problem was not properly implemented.')
Exemple #36
0
    def report(self):
        total = toc()
        md = self.metadata

        # compare errors measured by assemble and errornorm
        # TODO implement generally (if listDict[fcional]['testable'])
        # if self.testErrControl:
        #     for e in [[self.listDict['u_L2']['list'], self.listDict['u_L2test']['list'], 'L2'],
        #               [self.listDict['u_H1']['list'], self.listDict['u_H1test']['list'], 'H1']]:
        #         print('test ', e[2], sum([abs(e[0][i]-e[1][i]) for i in range(len(self.time_list))]))

        # report error norms, norms of divergence etc. for individual time steps
        with open(self.str_dir_name + "/report_time_lines.csv", 'w') as reportFile:
            report_writer = csv.writer(reportFile, delimiter=';', escapechar='\\', quoting=csv.QUOTE_NONE)
            # report_writer.writerow(self.problem.get_metadata_to_save())
            report_writer.writerow(["name", "what", "time"] + self.time_list)
            keys = sorted(self.listDict.keys())
            for key in keys:
                l = self.listDict[key]
                if l['list']:
                    abrev = l['abrev']
                    report_writer.writerow([md['name'], l['name'], abrev] + l['list'])
                    if 'scale' in l:
                        temp_list = [i/l['scale'][0] for i in l['list']]
                        report_writer.writerow([md['name'], "scaled " + l['name'], abrev+"s"] + temp_list +
                                               ['scale factor:' + str(l['scale'])])
                    if 'norm' in l:
                        if l['norm']:
                            temp_list = [i/l['norm'][0] for i in l['list']]
                            report_writer.writerow([md['name'], "normalized " + l['name'], abrev+"n"] + temp_list)
                        else:
                            info('Norm missing:' + str(l))
                            l['normalized_list_sec'] = []
                    if 'relative' in l:
                        norm_list = self.listDict[l['relative']]['list']
                        temp_list = [l['list'][i]/norm_list[i] for i in range(0, len(l['list']))]
                        self.listDict[key]['relative_list'] = temp_list
                        report_writer.writerow([md['name'], "relative " + l['name'], abrev+"r"] + temp_list)

        # report error norms, norms of divergence etc. averaged over cycles
        # IFNEED rewrite to averaging over cycles (must track number of steps in cycle, it can be different for each cycle)
        # NT for cases when cycle_length % dt != 0 will be inacurate (less with smaller time steps)
        # note: self.stepsInCycle is float

        # if self.second_list:
        #     with open(self.str_dir_name + "/report_seconds.csv", 'w') as reportFile:
        #         report_writer = csv.writer(reportFile, delimiter=';', escapechar='|', quoting=csv.QUOTE_NONE)
        #         report_writer.writerow(["name", "what", "time"] + self.second_list)
        #         keys = sorted(self.listDict.keys())
        #         for key in keys:
        #             l = self.listDict[key]
        #             if 'slist' in l and l['list']:
        #                 abrev = l['abrev']
        #                 values = l['slist']
        #                 # generate averages over seconds from list
        #                 for sec in self.second_list:
        #                     N0 = (sec-1)*self.stepsInCycle
        #                     N1 = sec*self.stepsInCycle
        #                     values.append(sqrt(sum([i*i for i in l['list'][N0:N1]]) / float(self.stepsInCycle)))
        #
        #                 report_writer.writerow([md['name'], l['name'], abrev] + values)
        #                 if 'scale' in l:
        #                     temp_list = [i/l['scale'][0] for i in values]
        #                     report_writer.writerow([md['name'], "scaled " + l['name'], abrev+"s"] + temp_list)
        #                 if 'norm' in l:
        #                     if l['norm']:
        #                         temp_list = [i/l['norm'][0] for i in values]
        #                         l['normalized_list_sec'] = temp_list
        #                         report_writer.writerow([md['name'], "normalized " + l['name'], abrev+"n"] + temp_list)
        #                     else:
        #                         info('Norm missing:' + str(l))
        #                         l['normalized_list_sec'] = []
        #                 if 'relative_list' in l:
        #                     temp_list = []
        #                     for sec in self.second_list:
        #                         N0 = (sec-1)*self.stepsInCycle
        #                         N1 = sec*self.stepsInCycle
        #                         temp_list.append(sqrt(sum([i*i for i in l['relative_list'][N0:N1]]) / float(self.stepsInCycle)))
        #                     l['relative_list_sec'] = temp_list
        #                     report_writer.writerow([md['name'], "relative " + l['name'], abrev+"r"] + temp_list)

        header_row = ["name", "totalTimeHours"]
        data_row = [md['name'], total / 3600.0]
        for key in ['u_L2', 'u_H1', 'u_H1w', 'p', 'u2L2', 'u2H1', 'u2H1w', 'p2', 'pgE', 'pgE2', 'd', 'd2', 'force_wall']:
            if key in self.listDict:
                l = self.listDict[key]
                header_row += ['last_cycle_'+l['abrev']]
                data_row += [l['slist'][-1]] if l['slist'] else [0]
                if 'relative_list_sec' in l and l['relative_list_sec']:
                    header_row += ['last_cycle_'+l['abrev']+'r']
                    data_row += [l['relative_list_sec'][-1]]
                elif key in ['p', 'p2']:
                    header_row += ['last_cycle_'+l['abrev']+'n']
                    data_row += [l['normalized_list_sec'][-1]] if 'normalized_list_sec' in l \
                                                                  and l['normalized_list_sec'] else [0]

        # save metadata. Can be loaded and used in postprocessing
        with open(self.str_dir_name + "/metadata", 'w') as reportFile:
            reportFile.write(self.get_metadata_to_save())

        # report without header
        with open(self.str_dir_name + "/report.csv", 'w') as reportFile:
            report_writer = csv.writer(reportFile, delimiter=';', escapechar='|', quoting=csv.QUOTE_NONE)
            report_writer.writerow(data_row)

        # report with header
        with open(self.str_dir_name + "/report_h.csv", 'w') as reportFile:
            report_writer = csv.writer(reportFile, delimiter=';', escapechar='|', quoting=csv.QUOTE_NONE)
            report_writer.writerow(header_row)
            report_writer.writerow(data_row)

        # report time cotrol
        with open(self.str_dir_name + "/report_timecontrol.csv", 'w') as reportFile:
            self.tc.report(reportFile, self.metadata['name'])

        self.remove_status_file()

        # create file showing all was done well
        f = open(md['name'] + "_OK.report", "w")
        f.close()
Exemple #37
0
    def __init__(self, args, tc, metadata):
        gs.GeneralSolver.__init__(self, args, tc, metadata)
        self.metadata['hasTentativeV'] = True

        self.solver_vel_tent = None
        self.solver_vel_cor = None
        self.solver_p = None
        self.solver_rot = None
        self.null_space = None

        # input parameters
        self.forceOutflow = args.fo
        self.useLaplace = args.laplace
        self.use_full_SUPG = args.cs
        self.bcv = 'NOT' if self.useLaplace else args.bcv
        if self.bcv == 'CDN':
            info('Using classical do nothing condition (Tn=0).')
        if self.bcv == 'DDN':
            info(
                'Using directional do nothing condition (Tn=0.5*negative(u.n)u).'
            )
        if self.bcv == 'LAP':
            info('Using laplace neutral condition (grad(u)n=0).')
        self.stabCoef = args.stab
        self.stabilize = (args.stab > DOLFIN_EPS)
        if self.stabilize:
            if self.use_full_SUPG:
                info(
                    'Used consistent streamline-diffusion stabilization with coef.: %f'
                    % args.stab)
            else:
                info(
                    'Used non-consistent streamline-diffusion stabilization with coef.: %f'
                    % args.stab)
        else:
            info('No stabilization used.')
        self.solvers = args.solvers
        self.useRotationScheme = args.r
        self.metadata['hasTentativeP'] = self.useRotationScheme
Exemple #38
0
    def solve(self, problem):
        self.problem = problem
        doSave = problem.doSave
        save_this_step = False
        onlyVel = problem.saveOnlyVel
        dt = self.metadata['dt']

        nu = Constant(self.problem.nu)
        self.tc.init_watch('init',
                           'Initialization',
                           True,
                           count_to_percent=False)
        self.tc.init_watch('solve',
                           'Running nonlinear solver',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('next',
                           'Next step assignments',
                           True,
                           count_to_percent=True)
        self.tc.init_watch('saveVel', 'Saved velocity', True)

        self.tc.start('init')

        mesh = self.problem.mesh

        # Define function spaces (P2-P1)
        self.V = VectorFunctionSpace(mesh, "Lagrange", 2)  # velocity
        self.Q = FunctionSpace(mesh, "Lagrange", 1)  # pressure
        self.W = MixedFunctionSpace([self.V, self.Q])
        self.PS = FunctionSpace(
            mesh, "Lagrange", 2)  # partial solution (must be same order as V)
        self.D = FunctionSpace(mesh, "Lagrange",
                               1)  # velocity divergence space

        # to assign solution in space W.sub(0) to Function(V) we need FunctionAssigner (cannot be assigned directly)
        fa = FunctionAssigner(self.V, self.W.sub(0))
        velSp = Function(self.V)

        problem.initialize(self.V, self.Q, self.PS, self.D)

        # Define unknown and test function(s) NS
        v, q = TestFunctions(self.W)
        w = Function(self.W)
        dw = TrialFunction(self.W)
        u, p = split(w)

        # Define fields
        n = FacetNormal(mesh)
        I = Identity(u.geometric_dimension())
        theta = 0.5  # Crank-Nicholson
        k = Constant(self.metadata['dt'])

        # Initial conditions: u0 velocity at previous time step u1 velocity two time steps back p0 previous pressure
        [u0, p0] = self.problem.get_initial_conditions([{
            'type': 'v',
            'time': 0.0
        }, {
            'type': 'p',
            'time': 0.0
        }])

        if doSave:
            problem.save_vel(False, u0)

        # boundary conditions
        bcu, bcp = problem.get_boundary_conditions(False, self.W.sub(0),
                                                   self.W.sub(1))

        # Define steady part of the equation
        def T(u):
            return -p * I + 2.0 * nu * sym(grad(u))

        def F(u, v, q):
            return (inner(T(u), grad(v)) - q * div(u)) * dx + inner(
                grad(u) * u, v) * dx

        # Define variational forms
        F_ns = (inner(
            (u - u0), v) / k) * dx + (1.0 - theta) * F(u0, v, q) + theta * F(
                u, v, q)
        J_ns = derivative(F_ns, w, dw)
        # J_ns = derivative(F_ns, w)  # did not work

        # NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns, form_compiler_parameters=ffc_options)
        NS_problem = NonlinearVariationalProblem(F_ns, w, bcu, J_ns)
        # (var. formulation, unknown, Dir. BC, jacobian, optional)
        NS_solver = NonlinearVariationalSolver(NS_problem)

        prm = NS_solver.parameters
        prm['newton_solver']['absolute_tolerance'] = 1E-08
        prm['newton_solver']['relative_tolerance'] = 1E-08
        # prm['newton_solver']['maximum_iterations'] = 45
        # prm['newton_solver']['relaxation_parameter'] = 1.0
        prm['newton_solver']['linear_solver'] = 'mumps'
        # prm['newton_solver']['lu_solver']['same_nonzero_pattern'] = True

        info(NS_solver.parameters, True)

        self.tc.end('init')

        # Time-stepping
        info("Running of direct method")
        ttime = self.metadata['time']
        t = dt
        step = 1
        while t < (ttime + dt / 2.0):
            self.problem.update_time(t, step)
            if self.MPI_rank == 0:
                problem.write_status_file(t)

            if doSave:
                save_this_step = problem.save_this_step

            # Compute
            begin("Solving NS ....")
            try:
                self.tc.start('solve')
                NS_solver.solve()
                self.tc.end('solve')
            except RuntimeError as inst:
                problem.report_fail(t)
                return 1
            end()

            # Extract solutions:
            (u, p) = w.split()
            fa.assign(velSp, u)
            # we are assigning twice (now and inside save_vel), but it works with one method save_vel for direct and
            #   projection (we could split save_vel to save one assign)

            if save_this_step:
                self.tc.start('saveVel')
                problem.save_vel(False, velSp)
                self.tc.end('saveVel')
            if save_this_step and not onlyVel:
                problem.save_div(False, u)
            problem.compute_err(False, u, t)
            problem.compute_div(False, u)

            # foo = Function(self.Q)
            # foo.assign(p)
            # problem.averaging_pressure(foo)
            # if save_this_step and not onlyVel:
            #     problem.save_pressure(False, foo)

            if save_this_step and not onlyVel:
                problem.save_pressure(False, p)

            # compute functionals (e. g. forces)
            problem.compute_functionals(u, p, t, step)

            # Move to next time step
            self.tc.start('next')
            u0.assign(velSp)
            t = round(t + dt, 6)  # round time step to 0.000001
            step += 1
            self.tc.end('next')

        info("Finished: direct method")
        problem.report()
        return 0
Exemple #39
0
# if args.solver == 'ipcs1':
    # PETScOptions.set('log_summary')

# Paralell run initialization
comm = mpi_comm_world()
rank = MPI.rank(comm)
# parameters["std_out_all_processes"] = False   # print only rank==0 process output
# parameters["ghost_mode"] = "shared_facet"     # may be needed for operating DG elements in parallel

# allows output using info() for the main process only
if rank == 0 or args.out == 'all':
    set_log_level(INFO)
else:
    set_log_level(INFO + 1)

info('Running on %d processor(s).' % MPI.size(comm))

if MPI.size(comm) > 1 and args.problem == 'womersley_cylinder':
    info('Womersley cylinder problem is not runnable in parallel due to method of construction of analytic solution,'
         ' which is used to describe boundary conditions.')  # the change of mesh format would be also needed
    exit()

# dynamically import selected solver and problem files
exec('from solvers.%s import Solver' % args.solver)
exec('from problems.%s import Problem' % args.problem)

# setup and parse problem- and solver-specific command-line arguments
parser = argparse.ArgumentParser()
Solver.setup_parser_options(parser)
Problem.setup_parser_options(parser)
args, remaining = parser.parse_known_args(remaining, args)
 def report(self, report_file, str_name):
     total_time = toc()
     info('Total time of %.0f s, (%.2f hours).' % (total_time, total_time/3600.0))
     sorted_by_time = []
     sorted_by_name = []
     sum = 0
     sum_percent = 0
     for value in self.watches.itervalues():
         if value[3]:
            sum += value[0]
         if value[4]:
            sum_percent += value[0]
         if not sorted_by_time:
             sorted_by_time.append(value)
         else:
             i = 0
             l = len(sorted_by_time)
             while i < l and value[0]<sorted_by_time[i][0]:
                 i += 1
             sorted_by_time.insert(i, value)
     for value in sorted_by_time:
         if value[0] > 0.000001:
             if value[4]:
                 info('   %-40s: %12.2f s %5.1f %% (%4.1f %%)' % (value[2], value[0], 100.0*value[0]/sum_percent, 100.0*value[0]/total_time))
             else:
                 info('   %-40s: %12.2f s         (%4.1f %%)' % (value[2], value[0], 100.0*value[0]/total_time))
         else:
             info('   %-40s: %12.2f s NOT USED' % (value[2], value[0]))
     info('   %-40s: %12.2f s         (%4.1f %%)' % ('Measured', sum, 100.0*sum/total_time))
     info('   %-40s: %12.2f s 100.0 %% (%4.1f %%)' % ('Base for percent values', sum_percent, 100.0*sum_percent/total_time))
     info('   %-40s: %12.2f s         (%4.1f %%)' % ('Unmeasured', total_time-sum, 100.0*(total_time-sum)/total_time))
     # report to file
     for key in self.watches.iterkeys():   # sort keys by name
         if not sorted_by_name:
             sorted_by_name.append(key)
         else:
             l = len(sorted_by_name)
             i = l
             while key < sorted_by_name[i-1] and i > 0:
                 i -= 1
             sorted_by_name.insert(i, key)
     report_header = ['Name', 'Total time']
     report_data = [str_name, total_time]
     for key in sorted_by_name:
         value = self.watches[key]
         report_header.append(value[2])
         report_header.append('part '+value[2])
         report_data.append(value[0])
         report_data.append(value[0]/total_time)
     report_header.append('part unmeasured')
     report_data.append((total_time-sum)/total_time)
     if report_file is not None:
         writer = csv.writer(report_file, delimiter=';', quotechar='|', quoting=csv.QUOTE_NONE)
         writer.writerow(report_header)
         writer.writerow(report_data)
Exemple #41
0
    def __init__(self, args, tc, metadata):
        self.has_analytic_solution = False
        self.problem_code = 'REAL'
        super(Problem, self).__init__(args, tc, metadata)

        self.name = 'test on real mesh'
        self.status_functional_str = 'outflow/inflow'
        self.last_inflow = 0

        # time settings
        self.itp_lengths = {
            1: 1.0,
            2: 0.9375,
        }
        self.cycle_length = self.itp_lengths[self.args.itp]

        # input parameters
        self.nu = self.args.nu  # kinematic viscosity
        self.factor = args.factor
        self.metadata['factor'] = self.factor
        self.scale_factor.append(self.factor)

        self.tc.start('mesh')
        # Import mesh
        try:
            self.mesh, self.facet_function = super(Problem,
                                                   self).loadMesh(args.mesh)
            info("Mesh name: " + args.mesh + "    " + str(self.mesh))
            f_ini = open('meshes/' + args.mesh + '.ini', 'r')
            reader = csv.reader(f_ini, delimiter=' ', escapechar='\\')
        except (EnvironmentError, RuntimeError):
            print(
                'Unable to open mesh.hdf5 or mesh.ini file. Check if the mesh was prepared to be used '
                'with \"real\" problem.')
            exit(1)

        # load inflows and outflows (interfaces) from mesh.ini file
        obj = None
        self.interfaces = []
        for row in reader:
            if not row:
                pass
            elif row[0] == 'volume':
                self.mesh_volume = float(row[1])
            elif row[0] == 'in':
                if obj is not None:
                    self.interfaces.append(obj)
                obj = {'inflow': True, 'number': row[1]}
            elif row[0] == 'out':
                if obj is not None:
                    self.interfaces.append(obj)
                obj = {'inflow': False, 'number': row[1]}
            else:
                if len(row) == 2:  # scalar values
                    obj[row[0]] = row[1]
                else:  # vector values
                    obj[row[0]] = [float(f) for f in row[1:]]
        self.interfaces.append(obj)
        f_ini.close()
        self.tc.end('mesh')

        # collect inflows and outflows into separate lists
        self.outflow_area = 0
        self.inflows = []
        self.outflows = []
        for obj in self.interfaces:
            if not obj['inflow']:
                self.outflow_area += float(obj['S'])
                self.outflows.append(obj)
            else:
                self.inflows.append(obj)
        info('Outflow area: %f' % self.outflow_area)

        # self.dsWall = Measure("ds", subdomain_id=1, subdomain_data=self.facet_function)
        self.normal = FacetNormal(self.mesh)

        # generate measures, collect measure lists
        self.inflow_measures = []
        for obj in self.interfaces:
            obj['measure'] = Measure("ds",
                                     subdomain_id=int(obj['number']),
                                     subdomain_data=self.facet_function)
            if obj['inflow']:
                self.inflow_measures.append(obj['measure'])
            else:
                self.outflow_measures.append(obj['measure'])

        self.listDict.update({
            'outflow': {
                'list': [],
                'name': 'outflow rate',
                'abrev': 'OUT',
                'slist': []
            },
            'inflow': {
                'list': [],
                'name': 'inflow rate',
                'abrev': 'IN',
                'slist': []
            },
            'oiratio': {
                'list': [],
                'name': 'outflow/inflow ratio (mass conservation)',
                'abrev': 'O/I',
                'slist': []
            },
        })
        for obj in self.outflows:
            n = obj['number']
            self.listDict.update({
                'outflow' + n: {
                    'list': [],
                    'name': 'outflow rate ' + n,
                    'abrev': 'OUT' + n,
                    'slist': []
                }
            })
        self.can_force_outflow = True
Exemple #42
0
def print_info():
  if MPI.rank(comm) == 0:
    info(dolfin.parameters, True)
Exemple #43
0
# if args.solver == 'ipcs1':
# PETScOptions.set('log_summary')

# Paralell run initialization
comm = mpi_comm_world()
rank = MPI.rank(comm)
# parameters["std_out_all_processes"] = False   # print only rank==0 process output
# parameters["ghost_mode"] = "shared_facet"     # may be needed for operating DG elements in parallel

# allows output using info() for the main process only
if rank == 0 or args.out == 'all':
    set_log_level(INFO)
else:
    set_log_level(INFO + 1)

info('Running on %d processor(s).' % MPI.size(comm))

if MPI.size(comm) > 1 and args.problem == 'womersley_cylinder':
    info(
        'Womersley cylinder problem is not runnable in parallel due to method of construction of analytic solution,'
        ' which is used to describe boundary conditions.'
    )  # the change of mesh format would be also needed
    exit()

# dynamically import selected solver and problem files
exec('from solvers.%s import Solver' % args.solver)
exec('from problems.%s import Problem' % args.problem)

# setup and parse problem- and solver-specific command-line arguments
parser = argparse.ArgumentParser()
Solver.setup_parser_options(parser)