⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gmfem.m

📁 matlab有限元分析工具,比经较全面的一个手册,请大家下载呀
💻 M
字号:
function u = gmfem(brep, mesh, conduct, source, userdata);%   u = gmfem(brep, mesh {, conduct { , source { , userdata}}});% This function solves the boundary value problem%    div (c grad u) = -f% The arguments are: %   brep: the domain on which the bvp is specified.%   mesh: a mesh of the domain, generated by gmmeshgen.%     Quadratic elements not supported; all elements interpreted%     as linear.%   conduct: A function that computes conductivity of the domain.  %      Overridden by the region's conductivity property.  Default is 1.%   source: A function that returns f, the source term.  Overridden by%     the regions's source property. Default is 0.%  Return value u is a vector of nodal values of the solution.  It%  is a zba.if nargin < 2  error('gmfem must have at least two arguments');endif nargin < 3  conduct = '(const 1.0)';endif nargin < 4  source = '(const 0.0)';endif nargin < 5   userdata = '';end%% This routine solves the finite element problem using%% the default ordering (min degree).if ~isa(brep,'zba')  error('First argument passed to gmfem not a zba');endif length(brep) < 1  error('First argument passed to gmfem not a brep');endglobal GM_BREP_TYPE_CODEtypecode = double(brep{0});if ~strcmpi(typecode, GM_BREP_TYPE_CODE)  error('First argument passed to gmfem not a brep');endif ~isa(mesh,'zba')  error('Second argument passed to gmfem not a zba');endif length(mesh) < 1  error('Second argument passed to gmfem not a mesh');endglobal GM_SIMPCOMP_TYPE_CODEtypecode = double(mesh{0});if ~strcmpi(typecode, GM_SIMPCOMP_TYPE_CODE)  error('Second argument passed to gmfem not a mesh');endglobal GM_GEO_ID_PROP;if ~strcmpi(gm_lookup_objprop(brep, GM_GEO_ID_PROP), ...            gm_lookup_objprop(mesh, GM_GEO_ID_PROP))  error('Brep-id code of mesh does not match with brep');enddi = double(brep{2});if di ~= 2 & di ~= 3  error('Only dims 2 and 3 supported.')endif brep{1} ~= di  error('Brep must be full dimensional.')end if mesh{2} ~= di  error('Dimension mismatch between mesh and brep')endif mesh{1} ~= di  error('Mesh must be full dimensional')end[scrap,numvtx] = size(mesh{4});[scrap,numtoplev] = size(mesh{5+di});[scrap,numtoplev2] = size(brep{5+di});if numtoplev ~= numtoplev2  error('Number of regions disagree between mesh and brep');end[scrap,numfacet] = size(mesh{4+di});[scrap,numfacet2] = size(brep{4+di});if numfacet ~= numfacet2  error('Number of facets disagree between mesh and brep');endnumtri = 0;tri = zba([]);for faceind = 0 : numtoplev - 1  [scrap, numtri1] = size(mesh{5+di}{1,faceind});  tri = [tri;mesh{5+di}{1,faceind}'];    numtri = numtri + numtri1;end[scrap,numtri] = size(mesh{5});[scrap,numtoplev] = size(brep{5+di});% Evaluate the conductivity and source.  Loop over top-level% faces of the brep and find the conductivity and source for each.con = zba(-ones(numtri,1));sourceterm = zba(zeros(numvtx,1));vtx_global_to_ordinal = ...   sparse((double(mesh{4}(0,:)))'+1,ones(numvtx,1), (0:numvtx-1)');vtx = mesh{4}(1:di,:)';tri = zba(full(vtx_global_to_ordinal(double(tri)+1)));pos = 0;for fa = 0 : numtoplev - 1  conduct1 = gm_lookup_prop(brep, di, fa, 'conductivity');  if length(conduct1) == 0    conduct1 = conduct;  end  facename = double(brep{5+di}{0,fa});  disp(sprintf('Conductivity on face %s is %s', facename, conduct1))  source1 = gm_lookup_prop(brep, di, fa, 'source');  if length(source1) == 0    source1 = source;  end  disp(sprintf('Source on face %s is %s', facename, source1))%  Evaluate conductivity at the midpoints of the mesh elements% (one-point integration).% tri1 has the vertices of the triangles in% the current toplev face, converted to ordinal numbering.  tri1 = full(vtx_global_to_ordinal(double(mesh{5+di}{1,fa})+1))';  [numtri1,scrap] = size(tri1);  if di == 2    midpoints = (vtx(tri1(:,1),:) + vtx(tri1(:,2),:) + ...                 vtx(tri1(:,3),:)) / 3;  else    midpoints = (vtx(tri1(:,1),:) + vtx(tri1(:,2),:) + ...                 vtx(tri1(:,3),:) + vtx(tri1(:,4),:)) / 4;  end  con1 = gm_conductivity(conduct1, userdata, midpoints);  [m,n] = size(con1);  if m ~= numtri1 | n ~= 1    error('Conductivity call returned a vector of the wrong size.')  end  if any(con1 <= 0)     error('Conductivity routine returned nonpositive conductivity');  end  con(pos:pos+numtri1 - 1) = con1;   sourceterm1 = gm_source(source1, userdata, midpoints);  [m,n] = size(sourceterm1);  if m ~= numtri1 | n ~= 1    error('Source-term call returned a vector of the wrong size.');  end  sourceterm(pos:pos+numtri1 - 1) = sourceterm1;  pos = pos + numtri1;endif any(con <= 0)  error('Some conductivities were not evaluated');end% Set up dirichlet and Neuman BC's.dirval = zba(zeros(numvtx,1));isdir = zba(zeros(numvtx,1));dircount = zba(zeros(numvtx,1));neusum = zba(zeros(numvtx,1));% Loop over faces of dimension di-1 and find out% their boundary values.for fa = 0 : numfacet - 1  bc = gm_strim(gm_lookup_prop(brep, di - 1, fa, 'bc'));  if length(bc) == 0    btype = 'n';    bfunc = '(const 0.0)';  else    %parse the boundary specification.    if bc(1) ~= '(' | bc(end) ~= ')'      error('Boundary condition must be an ordered pair (type func)');    end    bc = gm_strim(bc(2:length(bc)-1));    [btype,bfunc] = strtok(bc);    btype = lower(btype(1));    if btype ~= 'n' & btype ~= 'd'      error('Bc type must be either d or n');    end    bfunc = gm_strim(bfunc);    if length(bfunc) == 0      error('No boundary condition function specified')    end  end  facename = double(brep{4+di}{0,fa});  disp(sprintf('facet %s btype = %s bfunc = %s', ...	facename, btype, bfunc))  % Get the facets lying on this face, converted to  % ordinal indices.  facetlist = ...    zba(full(vtx_global_to_ordinal(double(mesh{4+di}{1,fa})+1))');  [numfacet1, scrap] = size(facetlist);    % String together the vertices of these facets and  % deduplicate for dirichlet bc.  vtxselect = sparse([],[],[],numvtx,1);  vtxselect(double(facetlist(:)) + 1) = ones(numfacet1 * di, 1);  vtxlist = find(vtxselect) - 1;  vtx1 = vtx(vtxlist,:);  [numvtx1, scrap] = size(vtx1);  if numvtx1 == 0    disp(sprintf('Warning: no vertices on facet %d:%d  %s', ...        di-1, fa, brep{4+di}{0,fa}))  else    bcval = gm_bdrycond(bfunc, userdata, vtx1);	    [m,n] = size(bcval);    if m ~= numvtx1 | n ~= 1      error('Bfunc return value is the wrong size');    end    if btype == 'd'      dirval(vtxlist) = dirval(vtxlist) + bcval;      dircount(vtxlist) = dircount(vtxlist) + ones(numvtx1,1);      isdir(vtxlist) = ones(numvtx1,1);    else      neusum  = neusum + gm_neumann(vtx, facetlist, bcval);    end  endend%% dirval holds the sums of the dirichlet boundary values;%% divide by dircount to make them average dirichlet values.dirval(find(isdir)) = dirval(find(isdir)) ./ dircount(find(isdir));%% At least one dirichlet node per connected component to make%% system nonsingular.compo_label = gm_mcompo(mesh);numcompo = max(double(compo_label)) + 1;for componum = 0 : numcompo - 1  if all(isdir(compo_label == componum) == 0)    disp(sprintf('Note: all vertices of component %d have Neumann condition',...          componum));    disp(sprintf('Boundary integral of Neumann data = %e',...       sum(neusum(compo_label == componum))));    disp('(Should be close to zero)');    ff = find(compo_label == componum);    if length(ff) > 0      disp(sprintf('Changing node %d to Dirichlet condition to make the problem well-posed', ff(1)));      isdir(ff(0)) = 1;      dirval(ff(0)) = 0;    end  endend  % Assemble the fe matrix and solve it.[K,f0] = gm_assemble(vtx, tri, isdir, dirval, con);neusum1 = neusum(isdir == 0);sourceterm1 = sourceterm(isdir == 0);f = f0 + neusum1 + sourceterm1;[m,n] = size(K);disp(sprintf('Assembled K is %d-by-%d and contains %d nonzero entries',... m,n,nnz(K)));startflops = flops;u0 = K \ f;endflops = flops;disp(sprintf('%d flops to solve linear system', endflops-startflops))% u0 has a value for all non-dirichlet boundary nodes.% Insert dirichlet nodes.u = zba(zeros(numvtx,1));u(find(isdir == 0)) = u0;u(find(isdir == 1)) = dirval(isdir == 1);% ------------------------------------------------------------------% Copyright (c) 1999 by Cornell University.  All rights reserved.% See the accompanying file 'Copyright' for authorship information,% the terms of the license governing this software, and disclaimers% concerning this software.% ------------------------------------------------------------------% This file is part of the QMG software.  % Version 2.0 of QMG, release date September 3, 1999% ------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -