Exemple #1
0
def create_empty(target,source):
	#create matrix			
	mlist = []
	nlist = []
	for si1 in xrange(target.nspaces):
		tspace = target.get_space(si1)
		for ci1 in xrange(tspace.ncomp):
			for bi1 in xrange(tspace.npatches):
				m = tspace.get_localndofs(ci1,bi1)
				mlist.append(m)
	for si2 in xrange(source.nspaces):
		sspace = source.get_space(si2)
		for ci2 in xrange(sspace.ncomp):						
			for bi2 in xrange(sspace.npatches):						
				n = sspace.get_localndofs(ci2,bi2)
				nlist.append(n)
	
	M = np.sum(np.array(mlist,dtype=np.int32))
	N = np.sum(np.array(nlist,dtype=np.int32))
	mat = PETSc.Mat()
	mat.create(PETSc.COMM_WORLD)
	mat.setSizes(((M, None),(N,None)))
	mat.setType('aij')
	mat.setLGMap(target.get_overall_lgmap(),cmap=source.get_overall_lgmap())
	mat.setUp()
	mat.assemblyBegin()
	mat.assemblyEnd()
		
	return mat
Exemple #2
0
def create_mono(target,source,blocklist,kernellist):
	#create matrix			
	mlist = []
	nlist = []			
	for si1 in xrange(target.nspaces):
		tspace = target.get_space(si1)
		for ci1 in xrange(tspace.ncomp):
			for bi1 in xrange(tspace.npatches):
				m = tspace.get_localndofs(ci1,bi1)
				mlist.append(m)
	for si2 in xrange(source.nspaces):
		sspace = source.get_space(si2)
		for ci2 in xrange(sspace.ncomp):						
			for bi2 in xrange(sspace.npatches):						
				n = sspace.get_localndofs(ci2,bi2)
				nlist.append(n)
				
	M = np.sum(np.array(mlist,dtype=np.int32))
	N = np.sum(np.array(nlist,dtype=np.int32))
	mat = PETSc.Mat()
	mat.create(PETSc.COMM_WORLD)
	mat.setSizes(((M, None),(N,None)))
	mat.setType('aij')
	mat.setLGMap(target.get_overall_lgmap(),cmap=source.get_overall_lgmap())
	
	#preallocate matrix

	#PRE-ALLOCATE IS NOT QUITE PERFECT FOR FACET INTEGRALS- IT WORKS BUT IS TOO MUCH!
	mlist.insert(0,0)
	mlist_adj = np.cumsum(mlist)
	dnnzarr = np.zeros(M,dtype=np.int32)
	onnzarr = np.zeros(M,dtype=np.int32)
	i = 0 #this tracks which row "block" are at
	#This loop order ensures that we fill an entire row in the matrix first
	#Assuming that fields are stored si,ci,bi, which they are!
	for si1 in xrange(target.nspaces):
		tspace = target.get_space(si1)
		for ci1 in xrange(tspace.ncomp):
			#only pre-allocate diagonal blocks, so one loop on bi
			for bi in xrange(tspace.npatches): #here we can assume tspace.mesh = sspace.mesh, and therefore tspace.blocks = sspace.nblocks)
				for si2 in xrange(source.nspaces):
					sspace = source.get_space(si2)
					for ci2 in xrange(sspace.ncomp):
						if ((si1,si2) in blocklist):
							bindex = blocklist.index((si1,si2))
							interior_x,interior_y,interior_z = get_interior_flags(kernellist[bindex])
							dnnz,onnz = two_form_preallocate_opt(tspace.mesh(),tspace,sspace,ci1,ci2,bi,interior_x,interior_y,interior_z)
							dnnz = np.ravel(dnnz)
							onnz = np.ravel(onnz)
							dnnzarr[mlist_adj[i]:mlist_adj[i+1]] = dnnzarr[mlist_adj[i]:mlist_adj[i+1]] + dnnz
							onnzarr[mlist_adj[i]:mlist_adj[i+1]] = onnzarr[mlist_adj[i]:mlist_adj[i+1]] + onnz
				i = i + 1 #increment row block
	mat.setPreallocationNNZ((dnnzarr,onnzarr))
	mat.setOption(PETSc.Mat.Option.IGNORE_ZERO_ENTRIES, False)
	mat.setOption(PETSc.Mat.Option.NEW_NONZERO_ALLOCATION_ERR, True)
	mat.setUp()
	mat.zeroEntries()
	
	return mat
Exemple #3
0
def create_matrix(mat_type,target,source,blocklist,kernellist):
	
	#block matrix
	if mat_type == 'nest' and (target.nspaces > 1 or source.nspaces > 1):
		#create matrix array
		matrices = []			
		for si1 in xrange(target.nspaces):
			matrices.append([])
			for si2 in xrange(source.nspaces):
				if ((si1,si2) in blocklist):
					bindex = blocklist.index((si1,si2))
					mat = create_mono(target.get_space(si1),source.get_space(si2),[(0,0),],[kernellist[bindex],])
				else:
					mat = create_empty(target.get_space(si1),source.get_space(si2))
				matrices[si1].append(mat)
		
		#do an empty assembly
		for si1 in xrange(target.nspaces):
			for si2 in xrange(source.nspaces):
				if ((si1,si2) in blocklist):
					bindex = blocklist.index((si1,si2))
					fill_mono(matrices[si1][si2],target.get_space(si1),source.get_space(si2),[(0,0),],[kernellist[bindex],],zeroassembly=True)
					#this catches bugs in pre-allocation and the initial assembly by locking the non-zero structure
					matrices[si1][si2].setOption(PETSc.Mat.Option.NEW_NONZERO_LOCATION_ERR, True)
					matrices[si1][si2].setOption(PETSc.Mat.Option.UNUSED_NONZERO_LOCATION_ERR, True)    
					#These are for zeroRows- the first keeps the non-zero structure when zeroing rows, the 2nd tells PETSc that the process only zeros owned rows
					matrices[si1][si2].setOption(PETSc.Mat.Option.KEEP_NONZERO_PATTERN, True) 
					matrices[si1][si2].setOption(PETSc.Mat.Option.NO_OFF_PROC_ZERO_ROWS, False)	
	
		#create nest
		mat = PETSc.Mat().createNest(matrices,comm=PETSc.COMM_WORLD)
	
	#monolithic matrix
	if (mat_type == 'nest' and (target.nspaces == 1 and source.nspaces == 1)) or mat_type == 'aij':
		#create matrix
		mat = create_mono(target,source,blocklist,kernellist)
		#do an empty assembly
		fill_mono(mat,target,source,blocklist,kernellist,zeroassembly=True)
	
	mat.assemble()

	#this catches bugs in pre-allocation and the initial assembly by locking the non-zero structure
	mat.setOption(PETSc.Mat.Option.NEW_NONZERO_LOCATION_ERR, True)
	mat.setOption(PETSc.Mat.Option.UNUSED_NONZERO_LOCATION_ERR, True)    
	mat.setOption(PETSc.Mat.Option.NEW_NONZERO_ALLOCATION_ERR, True)
	#These are for zeroRows- the first keeps the non-zero structure when zeroing rows, the 2nd tells PETSc that the process only zeros owned rows
	mat.setOption(PETSc.Mat.Option.KEEP_NONZERO_PATTERN, True) 
	mat.setOption(PETSc.Mat.Option.NO_OFF_PROC_ZERO_ROWS, False)	
	return mat