def subdomain_interpolate(pairs, V, reduce='last'): '''(f, chi), V -> Function fh in V such that fh|chi is f''' array = lambda f: f.vector().get_local() fs, chis = zip(*pairs) fs = np.column_stack([array(interpolate(f, V)) for f in fs]) x = np.column_stack([array(interpolate(Expression('x[%d]' % i, degree=1), V)) for i in range(V.mesh().geometry().dim())]) chis = [CompiledSubDomain(chi, tol=1E-10) for chi in chis] is_masked = np.column_stack([map(lambda xi, chi=chi: not chi.inside(xi, False), x) for chi in chis]) fs = mask.masked_array(fs, is_masked) if reduce == 'avg': values = np.mean(fs, axis=1) elif reduce == 'max': values = np.choose(np.argmax(fs, axis=1), fs.T) elif reduce == 'min': values = np.choose(np.argmin(fs, axis=1), fs.T) elif reduce == 'first': choice = [row.tolist().index(False) for row in is_masked] values = np.choose(choice, fs.T) elif reduce == 'last': choice = np.array([row[::-1].tolist().index(False) for row in is_masked], dtype=int) nsubs = len(chis) values = np.choose(nsubs-1-choice, fs.T) else: raise ValueError fh = Function(V) fh.vector().set_local(values) return fh
def deactivate_cells(surfaces, volumes, ncells_x, ncells_y): '''The tile dimension is 0.1 x 0.025 x 0.025 If the grid is oooooo oxxxxo oxxxxo oooooo I want to deactive o ''' front = 0.025 back = (ncells_y-1)*0.025 left = 0.1 right = (ncells_x-1)*0.1 # Marking the boundary guys in_layer = CompiledSubDomain('x[0] > right || x[0] < left || x[1] > back || x[1] < front', left=left, right=right, front=front, back=back) predicate = lambda c: in_layer.inside(c.midpoint().array(), False) # Mark by only midpoint check bdry_cells = deactivate_volumes(volumes, tag=1, predicate=predicate) # Set the layer to 2 volumes.array()[bdry_cells] = 2 # Now we have created a difference between layer and interior # Collect exterior ports of vol1 as surfaces between (1, 2) ext_ports = interfaces_between(volumes, ext_tag=1, tagged_cells=bdry_cells, int_tag=2, with_true_bdry=False) # Get all the facets in 2 two_points = all_facets_of(mesh, bdry_cells, volumes, 2) # If I remove from them the ports I can safely kill of the remaining # facet; i.e. make them exterior surfaces.array()[list(set(two_points) - set(ext_ports))] = 0 # Do that for volumes as well volumes.array()[bdry_cells] = 2 return surfaces, volumes
def create_dirichlet_conditions(values, boundaries, function_spaces): """Create Dirichlet boundary conditions for given boundary values, boundaries and function space.""" # Check that the size matches if len(values) != len(boundaries): error( "The number of Dirichlet values does not match the number of Dirichlet boundaries." ) if len(values) != len(function_spaces): error( "The number of Dirichlet values does not match the number of function spaces." ) if len(boundaries) != len(function_spaces): error( "The number of Dirichlet boundaries does not match the number of function spaces." ) info("Creating %d Dirichlet boundary condition(s)." % len(values)) # Create Dirichlet conditions bcs = [] for (i, value) in enumerate(values): # Get current boundary boundary = boundaries[i] function_space = function_spaces[i] # Case 0: boundary is a string if isinstance(boundary, str): boundary = CompiledSubDomain(boundary) bc = DirichletBC(function_space, value, boundary) # Case 1: boundary is a SubDomain elif isinstance(boundary, SubDomain): bc = DirichletBC(function_space, value, boundary) # Case 2: boundary is defined by a MeshFunction elif isinstance(boundary, tuple): mesh_function, index = boundary bc = DirichletBC(function_space, value, mesh_function, index) # Unhandled case else: error( "Unhandled boundary specification for boundary condition. " "Expecting a string, a SubDomain or a (MeshFunction, int) tuple." ) bcs.append(bc) return bcs
def test_mpi_dependent_jiting(): # FIXME: Not a proper unit test... from dolfin import (Expression, UnitSquareMesh, Function, TestFunction, Form, FunctionSpace, dx, CompiledSubDomain, SubSystemsManager) # Init petsc (needed to initalize petsc and slepc collectively on # all processes) SubSystemsManager.init_petsc() try: import mpi4py.MPI as mpi except ImportError: return try: import petsc4py.PETSc as petsc except ImportError: return # Set communicator and get process information comm = mpi.COMM_WORLD group = comm.Get_group() size = comm.Get_size() # Only consider parallel runs if size == 1: return rank = comm.Get_rank() group_comm_0 = petsc.Comm(comm.Create(group.Incl(range(1)))) group_comm_1 = petsc.Comm(comm.Create(group.Incl(range(1, 2)))) if size > 2: group_comm_2 = petsc.Comm(comm.Create(group.Incl(range(2, size)))) if rank == 0: e = Expression("4", mpi_comm=group_comm_0, degree=0) elif rank == 1: e = Expression("5", mpi_comm=group_comm_1, degree=0) assert (e) domain = CompiledSubDomain("on_boundary", mpi_comm=group_comm_1, degree=0) assert (domain) else: mesh = UnitSquareMesh(group_comm_2, 2, 2) V = FunctionSpace(mesh, "P", 1) u = Function(V) v = TestFunction(V) Form(u * v * dx)
def test_vertex_2d(self): mesh = UnitSquareMesh(8, 8) x = mesh.coordinates() min_ = np.min(x, axis=0) max_ = np.max(x, axis=0) tol = 1E-9 # The precision in gmsh isn't great, probably why DOLFIN's # periodic boundary computation is not working # Check x periodicity master = CompiledSubDomain('near(x[0], A, tol)', A=min_[0], tol=tol) slave = CompiledSubDomain('near(x[0], A, tol)', A=max_[0], tol=tol) shift_x = np.array([max_[0]-min_[0], 0]) to_master = lambda x, shift=shift_x: x - shift error, mapping = compute_vertex_periodicity(mesh, master, slave, to_master) self.assertTrue(error < 10*tol) _, mapping = compute_entity_periodicity(1, mesh, master, slave, to_master) self.assertTrue(len(list(mapping.keys())) == 8)
def test_tiling(self): tile = UnitSquareMesh(2, 2) mf = MeshFunction('size_t', tile, tile.topology().dim() - 1, 0) CompiledSubDomain('near(x[0], 0.5) || near(x[1], 0.5)').mark(mf, 1) mesh_data = {} mesh_data = load_data(tile, mf, dim=1, data=mesh_data) mesh, mesh_data = TileMesh(tile, shape=(23, 13), mesh_data=mesh_data) f = mf_from_data(mesh, mesh_data)[1] self.assertTrue( np.linalg.norm(mesh.coordinates().min(axis=0) - np.zeros(2)) < 1E-13) self.assertTrue( np.linalg.norm(mesh.coordinates().max(axis=0) - np.array([23., 13.])) < 1E-13) self.assertTrue(23 * 13 * 4 == sum(1 for _ in SubsetIterator(f, 1)))
def TileMesh(tile, shape, mesh_data={}, TOL=1E-9): ''' [tile tile; tile tile; tile tile; tile tile] The shape is an ntuple describing the number of pieces put next to each other in the i-th axis. mesh_data : (tdim, tag) -> [entities] is the way to encode mesh data of the tile. ''' # Sanity for glueing gdim = tile.geometry().dim() assert len(shape) <= gdim, (shape, gdim) # While evolve is general mesh writing is limited to simplices only (FIXME) # so we bail out early assert str(tile.ufl_cell()) in ('interval', 'triangle', 'tetrahedron') t = Timer('evolve') # Do nothing if all(v == 1 for v in shape): return tile, mesh_data # We want to evolve cells, vertices of the mesh using geometry information # and periodicity info x = tile.coordinates() min_x = np.min(x, axis=0) max_x = np.max(x, axis=0) shifts = max_x - min_x shifts_x = [] # Geometry vertex_mappings = [] # Periodicity # Compute geometrical shift for EVERY direction: for axis in range(len(shape)): shift = shifts[axis] # Vector to shift cell vertices shift_x = np.zeros(gdim); shift_x[axis] = shift shifts_x.append(shift_x) # Compute periodicity in the vertices to_master = lambda x, shift=shift_x: x - shift # Mapping facets master = CompiledSubDomain('near(x[i], A, tol)', i=axis, A=min_x[axis], tol=TOL) slave = CompiledSubDomain('near(x[i], A, tol)', i=axis, A=max_x[axis], tol=TOL) error, vertex_mapping = compute_vertex_periodicity(tile, master, slave, to_master) # Fail when exended direction is no periodic assert error < 10*TOL, error vertex_mappings.append(vertex_mapping) # The final piece of information is cells cells = np.empty((tile.num_cells(), tile.ufl_cell().num_vertices()), dtype='uintp') cells.ravel()[:] = tile.cells().flat # Evolve the mesh by tiling along the last direction in shape while shape: x, cells, vertex_mappings, shape = \ evolve(x, cells, vertex_mappings, shape, shifts_x, mesh_data=mesh_data) info('\tEvolve took %g s ' % t.stop()) # We evolve data but the mesh function is made out of it outside mesh = make_mesh(x, cells, tdim=tile.topology().dim(), gdim=gdim) return mesh, mesh_data
def broken_norm(norm, subdomains, mesh=None): '''Eval norm on subdomains and combine''' # Subdomains can be string -> get compile if isinstance(first(subdomains), str): subdomains = [CompiledSubDomain(s, tol=1E-10) for s in subdomains] mesh = None def get_norm(u, uh): assert len(subdomains) == len(u) V = uh.function_space() mesh = V.mesh() cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) error = 0 for subd_i, u_i in zip(subdomains, u): cell_f.set_all(0) # Reset! # Pick an edge subd_i.mark(cell_f, 1) mesh_i = SubMesh(mesh, cell_f, 1) # Edge local function space Vi = FunctionSpace(mesh_i, V.ufl_element()) # The solution on it uh_i = interpolate(uh, Vi) # And the error there error_i = norm(u_i, uh_i) error += error_i**2 error = sqrt(error) return error # Done return get_norm # CompiledSubDomain -> will be used to mark (go to base case) if hasattr(first(subdomains), 'mark'): return broken_norm(norm, subdomains, mesh=mesh) # Tuples of (tag, mesh_function) # Do some consistency checks; same mesh _, = set(first(p).mesh().id() for p in subdomains) mesh = first(first(subdomains)).mesh() # Cell functions ? _, = set(first(p).dim() for p in subdomains) dim = first(first(subdomains)).dim() assert mesh.topology().dim() == dim def get_norm(u, uh, mesh=mesh): assert len(subdomains) == len(u) V = uh.function_space() assert mesh.id() == V.mesh().id() error = 0 # NOTE: u is tag -> solution for subd, tag in subdomains: mesh_i = SubMesh(mesh, subd, tag) # Edge local function space Vi = FunctionSpace(mesh_i, V.ufl_element()) # The solution on it uh_i = interpolate(uh, Vi) # And the error there error_i = norm(u[tag], uh_i) error += error_i**2 error = sqrt(error) return error # Done return get_norm
Created on Thu Feb 13 21:49:47 2020 @author: alexanderniewiarowski """ from dolfin import Constant, CompiledSubDomain, DirichletBC try: from dolfin_adjoint import * ADJOINT = True except ModuleNotFoundError: ADJOINT = False # UNIT INTERVAL MESH BOUNDARIES bd_all_1D = CompiledSubDomain("near(x[0], 0) || near(x[0], 1)") bd_x_mid_1D = CompiledSubDomain("near(x[0], 0.5)") # UNIT SQUARE MESH BOUNDARIES bd_all = CompiledSubDomain("on_boundary") # left and right bd_x = CompiledSubDomain("(near(x[0], 0) && on_boundary) || (near(x[0], 1) && on_boundary)") # bottom and top bd_y = CompiledSubDomain("(near(x[1], 0) && on_boundary) || (near(x[1], 1) && on_boundary)") # x=0.5 bd_x_mid = CompiledSubDomain("near(x[0], 0.5)")
def bottom_boundary(x, on_boundary): return on_boundary and near(x[1], 0.0) def top_boundary(x, on_boundary): return on_boundary and near(x[1], 15.0E-3) ################################### FE part ################################### P1 = FiniteElement('P', 'triangle', 2) element = MixedElement([P1, P1, P1]) ME = FunctionSpace(mesh, element) subdomain = CompiledSubDomain( '(pow((x[0] - 7.5E-3), 2) + pow((x[1] - 7.5E-3), 2)) <= pow(2.5E-3, 2)') subdomains = MeshFunction("size_t", mesh, 2) subdomains.set_all(0) subdomain.mark(subdomains, 1) fc = Constant(2.0) # FCD V0_r = FunctionSpace(mesh, 'DG', 0) fc_function = Function(V0_r) fc_val = [0.0, fc] help = np.asarray(subdomains.array(), dtype=np.int32) fc_function.vector()[:] = np.choose(help, fc_val) zeroth = plot(fc_function, title="Fixed charge density, $c^f$") plt.colorbar(zeroth) plot(fc_function) plt.xlim(0.0, 0.015)
comm, [Point(0.0, 0.0, 0.0), Point(float(lmbdax), 1.0, float(lmbdaz))], [nx, ny, nz], CellType.Type.tetrahedron) # Shift the mesh to line up with the initial step function condition scale = db * (1.0 - db) shift = Expression(("0.0", "x[1]*(H - x[1])/S*A*cos(pi/Lx*x[0])*cos(pi/Lz*x[2])", "0.0"), A=0.02, Lx=lmbdax, Lz=lmbdaz, H=1.0, S=scale, degree=4) V = VectorFunctionSpace(mesh, "CG", 1) displacement = interpolate(shift, V) ALE.move(mesh, displacement) # Entrainment functional measures de = 1 cf = MeshFunction("size_t", mesh, mesh.topology().dim(), 0) CompiledSubDomain("x[1] > db - DOLFIN_EPS", db=db).mark(cf, de) dx = Measure("dx", subdomain_data=cf) # Setup particles pres = 25 x = RandomBox(Point(xmin, ymin, zmin), Point(xmax, ymax, zmax)).generate([pres, pres, pres]) s = np.zeros((len(x), 1), dtype=np.float_) # Interpolate initial function onto particles, index slot 1 property_idx = 1 ptcls = particles(x, [s], mesh) # Define the variational (projection problem) k = 1 W_e = FiniteElement("DG", mesh.ufl_cell(), k) T_e = FiniteElement("DG", mesh.ufl_cell(), 0)
if found: ch_values[entity] = p_values[p_entity] break return child_f # ------------------------------------------------------------------- if __name__ == '__main__': from dolfin import (CompiledSubDomain, DomainBoundary, SubsetIterator, UnitSquareMesh, Facet) from xii import EmbeddedMesh mesh = UnitSquareMesh(4, 4) surfaces = MeshFunction('size_t', mesh, 2, 0) CompiledSubDomain('x[0] > 0.5-DOLFIN_EPS').mark(surfaces, 1) # What should be trasfered f = MeshFunction('size_t', mesh, 1, 0) DomainBoundary().mark(f, 1) CompiledSubDomain('near(x[0], 0.5)').mark(f, 1) # Assign funky colors for i, e in enumerate(SubsetIterator(f, 1), 1): f[e] = i ch_mesh = EmbeddedMesh(surfaces, 1) ch_f = transfer_markers(ch_mesh, f) # Every color in child is found in parent and we get the midpoint right p_values, ch_values = list(f.array()), list(ch_f.array()) for ch_value in set(ch_f.array()) - set((0, )):
def left_boundary(x, on_boundary): return on_boundary and near(x[0], 0.0) def right_boundary(x, on_boundary): return on_boundary and near(x[0], 15.0e-3) def bottom_boundary(x, on_boundary): return on_boundary and near(x[1], 0.0) def top_boundary(x, on_boundary): return on_boundary and near(x[1], 15.0e-3) ################################### FE part ################################### P1 = FiniteElement('P', 'triangle', 2) element = MixedElement([P1, P1, P1]) ME = FunctionSpace(mesh, element) subdomain = CompiledSubDomain("x[0] >= 5.0e-3 && x[0] <= 10.0e-3 && x[1] >= 5.0e-3 && x[1] <= 10.0e-3") subdomains = MeshFunction("size_t", mesh, 2) subdomains.set_all(0) subdomain.mark(subdomains, 1) fc = Constant(2.0) # FCD V0_r = FunctionSpace(mesh, 'DG', 0) fc_function = Function(V0_r) fc_val = [0.0, fc] help = np.asarray(subdomains.array(), dtype = np.int32) fc_function.vector()[:] = np.choose(help, fc_val) zeroth = plot(fc_function, title = "Fixed charge density, $c^f$") plt.colorbar(zeroth) plot(fc_function) plt.xlim(0.0, 0.015)
f.write(options) # Options and alpha go as comments f.write('# %s\n' % alpha_str) print RED % (header % str(alpha)) wh, mms_data = analyze(module, (args.case0, args.ncases), alpha, args.norm, logfile) if args.plot: out = './plots/wh_%s_%s' % (problem, alpha_str) out = '_'.join([out, '%dsub.pvd']) out = os.path.join(savedir, out) eout = './plots/w_%s_%s' % (problem, alpha_str) eout = '_'.join([eout, '%dsub.pvd']) eout = os.path.join(savedir, eout) mesh = wh[0].function_space().mesh() facet_f = MeshFunction('size_t', mesh, mesh.topology().dim()-1, 0) CompiledSubDomain('near(x[0], 0)').mark(facet_f, 1) CompiledSubDomain('near(x[1], 0)').mark(facet_f, 2) CompiledSubDomain('near(x[0], 1)').mark(facet_f, 3) CompiledSubDomain('near(x[1], 1)').mark(facet_f, 4) ds_ = Measure('ds', domain=mesh, subdomain_data=facet_f) n = FacetNormal(mesh) for i, (whi, whi_true) in enumerate(zip(wh, mms_data.solution)): whi.rename('f', '0') #whi.vector().zero() File(out % i) << whi
def model(self, parameters=None, logger=None): def format(arr): return np.array(arr) # Setup parameters, logger self.set_parameters(parameters) self.set_logger(logger) # Get parameters parameters = self.get_parameters() #SS#if not parameters.get('simulate'): #SS# return # Setup data self.set_data(reset=True) self.set_observables(reset=True) # Show simulation settings self.get_logger()('\n\t'.join([ 'Simulating:', *[ '%s : %r' % (param, parameters[param] if not isinstance( parameters[param], dict) else list(parameters[param])) for param in ['fields', 'num_elem', 'N', 'dt', 'D', 'alpha', 'tol'] ] ])) # Data mesh mesh = IntervalMesh(MPI.comm_world, parameters['num_elem'], parameters['L_0'], parameters['L_1']) # Fields V = {} W = {} fields_n = {} fields = {} w = {} fields_0 = {} potential = {} potential_derivative = {} bcs = {} R = {} J = {} # v2d_vector = {} observables = {} for field in parameters['fields']: # Define functions V[field] = {} w[field] = {} for space in parameters['spaces']: V[field][space] = getattr( dolfin, parameters['spaces'][space]['type'])( mesh, parameters['spaces'][space]['family'], parameters['spaces'][space]['degree']) w[field][space] = TestFunction(V[field][space]) space = V[field][parameters['fields'][field]['space']] test = w[field][parameters['fields'][field]['space']] fields_n[field] = Function(space, name='%sn' % (field)) fields[field] = Function(space, name=field) # Inital condition fields_0[field] = Expression( parameters['fields'][field]['initial'], element=space.ufl_element()) fields_n[field] = project(fields_0[field], space) fields[field].assign(fields_n[field]) # Define potential if parameters['potential'].get('kwargs') is None: parameters['potential']['kwargs'] = {} for k in parameters['potential']['kwargs']: if parameters['potential']['kwargs'][k] is None: parameters['potential']['kwargs'][k] = fields[k] potential[field] = Expression( parameters['potential']['expression'], degree=parameters['potential']['degree'], **parameters['potential']['kwargs']) potential_derivative[field] = Expression( parameters['potential']['derivative'], degree=parameters['potential']['degree'] - 1, **parameters['potential']['kwargs']) #Subdomain for defining Positive grain sub_domains = MeshFunction('size_t', mesh, mesh.topology().dim(), 0) #BC condition bcs[field] = [] if parameters['fields'][field]['bcs'] == 'dirichlet': BC_l = CompiledSubDomain('near(x[0], side) && on_boundary', side=parameters['L_0']) BC_r = CompiledSubDomain('near(x[0], side) && on_boundary', side=parameters['L_1']) bcl = DirichletBC(V, fields_n[field], BC_l) bcr = DirichletBC(V, fields_n[field], BC_r) bcs[field].extend([bcl, bcr]) elif parameters['fields'][field]['bcs'] == 'neumann': bcs[field].extend([]) # Residual and Jacobian R[field] = ( ((fields[field] - fields_n[field]) / parameters['dt'] * test * dx) + (inner(parameters['D'] * grad(test), grad(fields[field])) * dx) + (parameters['alpha'] * potential_derivative[field] * test * dx)) J[field] = derivative(R[field], fields[field]) # Observables observables[field] = {} files = { 'xdmf': XDMFFile(MPI.comm_world, self.get_paths()['xdmf']), 'hdf5': HDF5File(MPI.comm_world, self.get_paths()['hdf5'], 'w'), } files['hdf5'].write(mesh, '/mesh') eps = lambda n, key, field, observables, tol: ( n == 0) or (abs(observables[key]['total_energy'][n] - observables[ key]['total_energy'][n - 1]) / (observables[key]['total_energy'][0]) > tol) flag = {field: True for field in parameters['fields']} tol = { field: parameters['tol'][field] if isinstance( parameters['tol'], dict) else parameters['tol'] for field in parameters['fields'] } phases = {'p': 1, 'm': 2} n = 0 problem = {} solver = {} while (n < parameters['N'] and any([flag[field] for field in parameters['fields']])): self.get_logger()('Time: %d' % (n)) for field in parameters['fields']: if not flag[field]: continue # Solve problem[field] = NonlinearVariationalProblem( R[field], fields[field], bcs[field], J[field]) solver[field] = NonlinearVariationalSolver(problem[field]) solver[field].solve() # Get field array array = assemble( (1 / CellVolume(mesh)) * inner(fields[field], w[field]['Z']) * dx).get_local() # Observables observables[field]['Time'] = parameters['dt'] * n # observables[field]['energy_density'] = format(0.5*dot(grad(fields[field]),grad(fields[field]))*dx) observables[field]['gradient_energy'] = format( assemble(0.5 * dot(grad(fields[field]), grad(fields[field])) * dx(domain=mesh))) observables[field]['landau_energy'] = format( assemble(potential[field] * dx(domain=mesh))) observables[field]['diffusion_energy'] = format( assemble( project( div(project(grad(fields[field]), V[field]['W'])), V[field]['Z']) * dx(domain=mesh)) ) #Diffusion part of chemical potential observables[field]['spinodal_energy'] = format( assemble( potential_derivative[field] * dx(domain=mesh))) #Spinodal part of chemical potential observables[field]['total_energy'] = parameters[ 'D'] * observables[field]['gradient_energy'] + parameters[ 'alpha'] * observables[field]['landau_energy'] observables[field]['chi'] = parameters['alpha'] * observables[ field]['diffusion_energy'] - parameters['D'] * observables[ field]['spinodal_energy'] # Phase observables sub_domains.set_all(0) sub_domains.array()[:] = np.where(array > 0.0, phases['p'], phases['m']) phases_dxp = Measure('dx', domain=mesh, subdomain_data=sub_domains) for phase in phases: dxp = phases_dxp(phases[phase]) observables[field]['Phi_0%s' % (phase)] = format( assemble(1 * dxp)) observables[field]['Phi_1%s' % (phase)] = format( assemble(fields[field] * dxp)) observables[field]['Phi_2%s' % (phase)] = format( assemble(fields[field] * fields[field] * dxp)) observables[field]['Phi_3%s' % (phase)] = format( assemble(fields[field] * fields[field] * fields[field] * dxp)) observables[field]['Phi_4%s' % (phase)] = format( assemble(fields[field] * fields[field] * fields[field] * fields[field] * dxp)) observables[field]['Phi_5%s' % (phase)] = format( assemble(fields[field] * fields[field] * fields[field] * fields[field] * fields[field] * dxp)) observables[field]['gradient_energy_%s' % (phase)] = format( assemble( 0.5 * dot(grad(fields[field]), grad(fields[field])) * dxp)) observables[field]['landau_energy_%s' % (phase)] = format( assemble(potential[field] * dxp)) observables[field][ 'total_energy_%s' % (phase)] = parameters['D'] * observables[field][ 'gradient_energy_%s' % (phase)] + parameters['alpha'] * observables[ field]['landau_energy_%s' % (phase)] observables[field][ 'diffusion_energy_%s' % (phase)] = format( assemble( project( div( project(grad(fields[field]), V[field]['W'])), V[field]['Z']) * dxp)) #Diffusion part of chemical potential observables[field][ 'spinodal_energy_%s' % (phase)] = format( assemble( potential_derivative[field] * dxp)) #Spinodal part of chemical potential observables[field][ 'chi_%s' % (phase)] = parameters['alpha'] * observables[field][ 'spinodal_energy_%s' % (phase)] - parameters['D'] * observables[field][ 'diffusion_energy_%s' % (phase)] files['hdf5'].write(fields[field], '/%s' % (field), n) files['xdmf'].write(fields[field], n) fields_n[field].assign(fields[field]) self.set_data({field: array}) self.set_observables({field: observables[field]}) flag[field] = eps(n, field, fields[field], self.get_observables(), tol[field]) n += 1 for file in files: files[file].close() return