You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

466 lines
12 KiB

function [pts,tri] = xmesh2dlin(filename,varargin)
%-------------------------------------------------------------------------%
% XMESH2D stands for EXACT MESHER 2d. Given an arbitrary collection of
% NURBS curves up through polynomial degree 3 in 2D, XMESH2d will generate
% a higher order triangular mesh that exactly matches the input geometry.
%
% INPUT:
% filename: The filename of a .spline file containing the curves that
% define the problem geometry.
%
% Output:
% NODE: A nNodesx3 array containing the coordinates and weights of the
% nodes that make up the mesh.
%
% IEN: a 10xnel array containing the mesh connectivity information.
%
% filename.neu: xmesh2d also writes out the mesh information int he
% standard gambit neu trail fil e format to the file <filename>.neu
%-------------------------------------------------------------------------%
if nargin == 1
options.output = false;
options.debug = false;
options.smoothWeights = true;
options.smoothNodes = false;
options.thresh=1.1;
options.hmax=.3;
elseif nargin == 2
options = varargin{1};
if ~exist('options.output') %#ok<*EXIST>
options.output = false;
end
if ~exist('options.debug')
options.debug = false;
end
if ~isfield(options,'smoothWeights')
options.smoothWeights = true;
end
if ~exist('options.smoothNodes')
options.smoothNodes = false;
end
if ~isfield(options,'thresh')
options.thresh= 1.1;
end
if ~isfield(options,'hmax')
options.hmax=.3;
end
end
% Input Parser
[P,KV,~,~,~,face] = splineFileIn(filename);
% Normalize the knot vectors to span [0 1]
for kk = 1:numel(KV)
KV{kk} = KV{kk}/KV{kk}(end);
end
% Subdividing the inputted NURBS curves into polygons
[node,edge,kvloc] = NURBS2poly(P,KV,options.thresh);
hdata.hmax=options.hmax*(max(node(:,1))-min(node(:,1)));
% Feeding the polygons into mesh2d
[pts,tri,~] = xmeshfaces(node,edge,P,KV,kvloc,face,hdata,options);
return
function [node,linnode,BFLAG,CFLAG]= elevateMesh(pts,tri,bNode,bflag,bc,p)
side = [1 2; 2 3; 3 1];
side10 = [1 4 5 2; 2 6 7 3; 3 8 9 1];
node = cell(length(tri),1);
linnode = cell(length(tri),1);
BFLAG = zeros(numel(bNode),4);
ctr = 1;
d = 14;
% Define CFLAG as a flag if the current element is curved.
CFLAG = false(length(tri),1);
cctr=0;
for ee = 1:length(tri)
vert = pts(tri(ee,:),:);
linnode{ee} = round(gen_net(vert)*10^d)/10^d;
node{ee} = round(gen_net(vert)*10^d)/10^d;
%Check to see if the current triangle is a boundary triangle.
for bb = 1:numel(bNode)
% Check to see if the triangle has a side on the boundary.
for ss = 1:3
if all(single(node{ee}(side(ss,1),1:2)) == single(bNode{bb}(1,1:2))) && ...
all(single(node{ee}(side(ss,2),1:2)) == single(bNode{bb}(4,1:2)));
node{ee}(side10(ss,:),:) = bNode{bb};
linnode{ee}(side10(ss,:),3) = bNode{bb}(:,3);
BFLAG(ctr,1) = ee;
BFLAG(ctr,2) = ss;
BFLAG(ctr,3) = bflag(bb,1);
BFLAG(ctr,4) = bc(bflag(bb,1),2);
if p(bflag(bb,2))>1
CFLAG(ee) = true;
ss=evalNURBS(node{ee}(side10(ss,:),:),[0 0 0 0 1 1 1 1],0:.1:1);
if abs(ss(:,1).^2+ss(:,2).^2-1)>1e-10
cctr=cctr+1;
end
end
ctr=ctr+1;
elseif all(single(node{ee}(side(ss,2),1:2)) == single(bNode{bb}(1,1:2))) && ...
all(single(node{ee}(side(ss,1),1:2)) == single(bNode{bb}(4,1:2)));
node{ee}(side10(ss,:),:) = flipud(bNode{bb});
linnode{ee}(side10(ss,:),3) = flipud(bNode{bb}(:,3));
BFLAG(ctr,1) = ee;
BFLAG(ctr,2) = ss;
BFLAG(ctr,3) = bflag(bb,1);
BFLAG(ctr,4) = bc(bflag(bb,1),2);
if p(bflag(bb,2))>1
CFLAG(ee) = true;
ss=evalNURBS(node{ee}(side10(ss,:),:),[0 0 0 0 1 1 1 1],0:.1:1);
if abs(ss(:,1).^2+ss(:,2).^2-1)>1e-10
cctr=cctr+1;
end
end
ctr=ctr+1;
end
end
% Also check to see if the triangle has a vertex on the boundary.
% If it does, it is part of the blending layer, so it needs to be
% flagged.
% for vv = 1:3
% if single(node{ee}(vv,1:2)) == single(bNode{bb}(1,1:2)) || ...
% single(node{ee}(vv,1:2)) == single(bNode{bb}(4,1:2));
% if p(bflag(bb,2))>1
% CFLAG(ee) = true;
% end
% ctr=ctr+1;
% end
% end
end
end
return
function [node] = gen_net(vert)
% ----------------------------------gen_net------------------------------------%
% Generates the control net for the current triangular Bezier patch. Reads in
% the verticies of a triangle, and linearly interpolates the triangle to make a
% 10 control point bezier element.
% INPUT:
% vert: a matrix in the form [x1 y1; x2 y2; x3 y3] containing the verticies of a
% linear triangle, ordered counter clockwise from the bottom left vertex.
% v3
% | \
% | \
% | \
% | \
% v1----v2
% OUTPUT:
% node: a 10x3 array containing the control point coordinates and weights.
% The standard node ordering is shown below.
%
% 3
% |\
% | \
% 8 7
% | \
% | \
% 9 10 6
% | \
% | \
% 1--4--5--2
%
%------------------------------------------------------------------------------%
node(:,1:2) = [ vert(1,1:2);...
vert(2,1:2);...
vert(3,1:2);...
vert(1,1:2) + (vert(2,1:2)-vert(1,1:2))/3;...
vert(1,1:2) + (vert(2,1:2)-vert(1,1:2))*2/3;...
vert(2,1:2) + (vert(3,1:2)-vert(2,1:2))/3;...
vert(2,1:2) + (vert(3,1:2)-vert(2,1:2))*2/3;...
vert(3,1:2) + (vert(1,1:2)-vert(3,1:2))/3;...
vert(3,1:2) + (vert(1,1:2)-vert(3,1:2))*2/3];
node(10,1:2) = node(9,1:2) + (node(6,1:2)-node(9,1:2))/2;
if size(vert,2) ==3
node(4:10,3) = ones(7,1);
node(1:3,3) = vert(1:3,3);
else
node(:,3) = ones(10,1);
end
return
function [P,KV,p,BFLAG,BC,FACE] = splineFileIn(filename)
filename = [filename,'.spline'];
fileID = fopen(filename,'r');
% Read in the file header
for i=1:2
line = fgetl(fileID);
end
% Find the total number of curves
line = fgetl(fileID);
dims = sscanf(line, '%f');
nCurves = dims(1);
KV = cell(1,nCurves);
P = cell(1,nCurves);
BFLAG = cell(1,nCurves);
p = zeros(1,nCurves);
for cc = 1:nCurves
line = fgetl(fileID); %#ok<*NASGU>
dims = fscanf(fileID,'%u');
nCP = dims(1);
lKV = dims(2);
p(cc) = dims(3);
line=fgetl(fileID);
for ii = 1:nCP
line = fgetl(fileID);
tmpx = sscanf(line, '%lf');
P{cc}(ii,1) = tmpx(1); P{cc}(ii,2) = tmpx(2); P{cc}(ii,3) = tmpx(3);
end
line = fgetl(fileID);
line = fgetl(fileID);
KV{cc} = sscanf(line, '%lf');
KV{cc} = KV{cc}';
line = fgetl(fileID);
nKspan = length(unique(KV{cc}))-1;
for bb = 1:nKspan
line = fgetl(fileID);
BFLAG{cc}(bb,:) = sscanf(line, '%u');
end
end
line = fgetl(fileID);line = fgetl(fileID);line = fgetl(fileID);
NBC = sscanf(line, '%u');
BC = zeros(NBC,2);
for bb = 1:NBC
line = fgetl(fileID);
BC(bb,:) = sscanf(line,'%u');
end
line = fgetl(fileID);
if line ~= -1
fgetl(fileID);
line = fgetl(fileID);
nFace = sscanf(line,'%u');
FACE = cell(1,nFace);
for ff = 1:nFace
fgetl(fileID);
line = fgetl(fileID);
nCurve = sscanf(line,'%u');
for cc = 1:nCurve
line = fgetl(fileID);
FACE{ff}(cc) = sscanf(line,'%u');
end
end
else
FACE{1} = 1:nCurves;
end
fclose(fileID);
return
function [NODE, IEN,BFLAG,CFLAG]= elevateMeshAndSmooth(pts,tri,bNode)
side = [1 2; 2 3; 3 1];
side10 = [1 4 5 2; 2 6 7 3; 3 8 9 1];
node = cell(length(tri),1);
ctr = 1;
d = 14;
% Loop through elements in the mesh and elevate locally.
for ee = 1:length(tri)
vert = pts(tri(ee,:),:);
node{ee} = round(gen_net(vert)*10^d)/10^d;
end
% Create the global NODE and IEN arrays from the local arrays.
addpath('~/TriGA/')
addpath('~/TriGA/xmesh')
[NODE, IEN] = gen_arrays(node);
bNodeList = [];
g = zeros(2,max(IEN(:)));
% Find the displacement boundary conditions.
for ee = 1:length(IEN)
node = NODE(IEN(:,ee),:);
%Check to see if the current triangle is a boundary triangle.
for bb = 1:numel(bNode)
% Check to see if the triangle has a side on the boundary.
for ss = 1:3
if all(single(node(side(ss,1),1:2)) == single(bNode{bb}(1,1:2))) && ...
all(single(node(side(ss,2),1:2)) == single(bNode{bb}(4,1:2)));
ctr=ctr+1;
bNodeList = [bNodeList;IEN(side10(ss,:),ee)];
gloc = bNode{bb}(:,1:2) - node(side10(ss,:),1:2);
g(:,IEN(side10(ss,:),ee)) = gloc';
elseif all(single(node(side(ss,2),1:2)) == single(bNode{bb}(1,1:2))) && ...
all(single(node(side(ss,1),1:2)) == single(bNode{bb}(4,1:2)));
bNodeList = [bNodeList;IEN(side10(ss,:),ee)];
gloc = flipud(bNode{bb}(:,1:2)) - node(side10(ss,:),1:2);
g(:,IEN(side10(ss,:),ee)) = gloc';
ctr=ctr+1;
end
end
end
end
% Linear elasticty smoothing to make the curvilinear mesh.
bNodes = unique(bNodeList);
NODE = LE2d(NODE,IEN,bNodes,g);
NODE(:,3) = 1;
NODE(:,1:2) = NODE(:,1:2)+g';
% Defining dummy BFLAG and CFLAG variables so this function will play nice
% in the TriGA environment. These will need to actaully be computed if this
% is found to be worthwhile.
BFLAG =[];
CFLAG =[];
return
function [newNode] = LE2d(NODE, IEN, bNodes,g)
% LE2d solves the 2D linear elasticity equations for the express purpose of
% calculating mesh deformation. Because of this, it does not account for
% traction and free boundary conditions. It simply claculates the global
% stiffness matrix, sets the forcing matric to zero and applies diriclet
% boundary conditions based on the geometry of the new mesh.
% Quadrature rules
[qPts, ~, w, ~] = quadData(16);
nq = length(w);
% Stiffness Properties
E = 100*10^9;
nu = .3;
lambda = nu*E/((1+nu)*(1-2*nu));
mu = E/(2*(1+nu));
D = [lambda + 2*mu, lambda, 0; lambda, lambda + 2*mu, 0; 0 0 mu];
% Mesh/ Geometry information
nel = length(IEN);
nen = 10;
nNodes = max(IEN(:));
nsd = 2;
ndof = nsd*(nNodes-length(bNodes));
nedof = nen*nsd;
%Initialize the global K and F matrices.
K = zeros(ndof);
F = zeros(ndof,1);
% Construct the ID array.
P = 1;
ID = zeros(nsd,nNodes);
for a = 1:nNodes
if find(a==bNodes)
ID(1,a) = 0;
ID(2,a) = 0;
else
ID(1,a) = P;
ID(2,a) = P+1;
P = P+2;
end
end
% Generate a lookup table for the basis.
[N,dN_du] = evaluateBasis(qPts);
% Loop over elements.
for ee = 1:nel
node = NODE(IEN(:,ee),:);
% Set the local stiffness matrix to zero.
k = zeros(nedof);
% Loop over quadrature points to construct k.
for qq = 1:nq
% Construct the B matrix
B = zeros(3,nedof);
[~, dR_dx,~, J_det] = tri10fast(node,N(:,qq),dN_du(:,:,qq));
for a = 1:nen
B(:,nsd*(a-1)+(1:2)) = [dR_dx(a,1), 0; ...
0, dR_dx(a,2);...
dR_dx(a,2), dR_dx(a,1)];
end
% Add the contributions of the current quad point to the local
% stiffness matrix.
J_det = abs(J_det);
k = k + w(qq)*B'*D*B*J_det;
end
% Assemble the local element stiffness matrix to the global stiffness
% matrix.
for a = 1:nen
for b = 1:nen
for i = 1:nsd
for j = 1:nsd
p = (a-1)*nsd+i;
q = (b-1)*nsd+j;
Pa = ID(i,IEN(a,ee));
Pb = ID(j,IEN(b,ee));
if Pa ~= 0 && Pb ~= 0
K(Pa,Pb) = K(Pa,Pb) + k(p,q);
elseif Pa~=0 && Pb ==0
F(Pa) = F(Pa) - k(p,q)*g(j,IEN(b,ee));
end
end
end
end
end
end
% Solve the system
d = K\F;
newNode = zeros(size(NODE));
for i = 1:nNodes
xidx = ID(1,i);
yidx = ID(2,i);
if xidx~=0
newNode(i,1:2) = NODE(i,1:2) + [d(xidx), d(yidx)];
else
newNode(i,1:2) = NODE(i,1:2);
end
end
return