Discussion Closed This discussion was created more than 6 months ago and has been closed. To start a new discussion with a link back to this one, click here.
How can I combine several subregions while "keeping the mesh"?
Posted 8 mar 2010, 10:40 GMT-5 9 Replies
Please login with a confirmed email address before reporting spam
(see attached figure).
After meshing i want to "remove" the internal boundaries
and keep the variable sized mesh.
At the end there should be only one subregion but the mesh should
stay "the same" as before.
How can I convert the internal boundaries to triangle edges
of a "combined mesh"?
Attachments:
Please login with a confirmed email address before reporting spam
I guess that there is no way to solve your question by using comsol gui tools. I thing that you should try via Matlab.
Try the procedure below:
1. create the live-link with matlab
2. export fem data as matlab structure (your variable is saved in the workspace as "fem" by default)
3. run the following matlab script:
%%%%%%%%%%%%%%
%- get element data...
ele=get(fem.mesh,'el');
%-get triangles...
tria=ele{3}.elem;
%- create new structure...
elestr{1}=struct('type','tri','elem',tria);
%- create new mesh object...
mobj=femmesh(node,elestr);
%- update comsol data
mobj=meshenrich(mobj);
femNew.mesh=mobj;
%%%%%%%%%%%%%
4. now "femNew" is the updated comsol structure having only mesh data information (as you are looking for)
5. import "femNew" in comsol and run your application mode.
I hope this can help you.
Please let me know if this works well!
Good luck
Pasquale
Please login with a confirmed email address before reporting spam
thank you for your answer! I got on the same path and below is some stuff i tried.
It is possible to extract the triangle information and create a new mesh without internal
sobdomain boundaries. So far so good.
It is also possible to create a new geometry from this new mesh and import it together
with the new mesh back to the Comsol interface.
But if I try to fit the new mesh to my own geometry (old geometry after removing
internal boundaries) I get following error:
"Geometry object and mesh object are not compatible."
I saw some small differences (in the order of 1e-20) in the coordinates of the edge
points of my new mesh and the edge point coordinatets of the geometry. Could
that be the reason? I tried to rescale the mesh coordinates, but the scaled mesh did not fit, too.
Any idea how I have to further modify the mesh or the existing geometry?
(I do not want to reset my application modes.)
-------------------------------------------------------------------------
%- read mesh data from fem structure
ele=get(fem.mesh,'el');
p=get(fem.mesh,'p');
%-get triangles...
tria=ele{3}.elem;
%- create new structure...
elestr{1}=struct('type','tri','elem',tria);
%- create new mesh object...
fem.mesh=femmesh(p,elestr);
%- update comsol data
fem.mesh=meshenrich(fem);
%generate geometry from mesh (import would work with this new geometry)
%fem=mesh2geom(fem);
%delete interior boundaries of geometry (import does not work with resulting geometry)
fem.geom=geomdel(fem.geom);
%meshplot(fem,'Boundmode','off');
%geomplot(fem)
%!!!!!! Import of 'fem' results in the error "Geometry object and mesh object are not compatible." !!!!!!!!
-----------------------------------------------------------------------------
some further code snippets:
%get mesh point coordinates from file
%d=importdata('mesh.mphtxt',' ',22);
%xy=d.data(1:end-1,:); %remove last line with NaN
%get mesh point coordinates from fem structure
xy=get(fem.mesh,'p')';
%remove scaling errors
%xw =3e-4; %specify width of geometry
%yw =1.5e-4; %specify height of geometry
%max(xy(:,1))-xw %errors before scaling
%min(xy(:,2))+yw %
%xy(:,1)=xy(:,1)*xw/max(xy(:,1));
%xy(:,2)=xy(:,2)*(-yw)/min(xy(:,2));
%max(xy(:,1))-xw %errors after scaling = 0
%min(xy(:,2))+yw %
%generate delaunay triangle mesh from mesh point coordinates
tri = DelaunayTri(xy(:,1),xy(:,2));
vertices=tri.Triangulation;
coord=tri.X;
%transform the matlab mesh to a comsol mesh structure fem.mesh
el = cell(1,0);
el{1} = struct('type','tri','elem',vertices');
fem.mesh = femmesh(coord',el);
fem.mesh = meshenrich(fem);
%meshplot(fem,'Boundmode','off');
%!!!!!! Import results in the same error "Geometry object and mesh object are not compatible." !!!!!!!
Please login with a confirmed email address before reporting spam
the "meshenrich" function creates also a new geometry decomposition based just only on mesh data. This geometry may be different from the original one (that one you created after removing internal boundaries). The approach I suggested you can be useful but you need to redefine all domain and boundary conditions.
Please tell me why you need to delete interior boundaries from your application? Is there some specific reason?
Pasquale
Please login with a confirmed email address before reporting spam
I want to generate a mesh with variable mesh element size for semiconductor simulations.
My current approach is:
- Define a "mesh-size expression" mesh_size(x,y) in the scalar expressions.
- Copy the fem structure "fem" to a dummy fem structure "dummy_fem"
- Initialize the fem structure and calculate contour lines of the expression mesh_size(x,y).
- Take the contour lines as subdomain boundaries.
- Mesh the subdomains with different mesh sizes, according to the "countour-height".
- Remove the internal boundaries.
- Transfer the new mesh of "dummy_fem" to "fem", including all boundary conditions ect.
If i do not remove the boundaries i would have to specify the physics for a lot of regions
where the physics is the same.
Another approach was to start with a coarse triangle mesh and refine
the triangles if triangle-size is smaller than mesh_size(x,y). This
takes too much time and the mesh is too fine at some locations.
Is there a way to import a mesh without meshenrich?
If I find another way to get my wanted mesh point coordinates (and use the delaunay triangulation
function...) I would get the same problem with the mesh import.
So the main question is: "How to import a mesh for a already existing geometry?"
Please login with a confirmed email address before reporting spam
I understand your problem and your needs, but at the moment I have no tip.
I am sorry. Please keep me updated if you find a good solution to your issue.
Regards
Pasquale
Please login with a confirmed email address before reporting spam
I digged a little bit in the mesh object. If I export a single subdomain,
extract triangle coordinates, build a new mesh... the import also doesn't work.
The problem seems to be that meshenrich uses a differend indexing order
for the boundary edges.
If i apply
el=get(fem.mesh,'el');
el{1}
el{2}
el{3}
to the two meshes (first one after export, second one build from
extracted information) i get different results:
Case 1:------------------------------------------------------------------
type: 'vtx'
elem: [1 8 12 20]
dom: [1 3 2 4]
type: 'edg'
elem: [2x12 double]
dom: [2 2 1 1 2 1 4 3 4 3 3 4]
ud: [2x12 double]
param: [2x12 double]
type: 'tri'
elem: [3x26 double]
dom: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
Case 2:-----------------------------------------------------------------
type: 'vtx'
elem: [1 8 12 20]
dom: [1 2 3 4]
type: 'edg'
elem: [2x12 double]
dom: [2 4 2 2 4 4 3 1 3 1 3 1]
ud: [2x12 double]
param: [2x12 double]
type: 'tri'
elem: [3x26 double]
dom: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1]
--------------------------------------------------------------------------
=> The "dom" numbers are mixed up.
(The order of the el-fields is also different, but this should not matter.
Above I wrote the el-fields in the same order for easy comparison.)
I do not like the Comsol-Indexing system!!! *grrrrr*
It already took me a lot of time in the past.
I wrote something to find out the index of a point or boundary at
specified coordinates and now I can use my own indexing for
complex geometries.
Maybe something similiar will work for this issue.
Or maybe I will not work with Comsol any more ;).
Please login with a confirmed email address before reporting spam
The param field of the mesh after meshenrich contains absolute values while
the param field of the original mesh contains relative values.
Please login with a confirmed email address before reporting spam
The functions below might not work for all geometry and might be slow.
However, they do the job for me and you may modify the functions for your own needs.
- Save the attached functions and add them to your matlab path (Matlab menu: File=>Set Path...)
- Export your fem structure to the Matlab workspace as "fem".
- Run following command:
fem=remove_internal_boundaries(fem)
- Import the new fem structure "fem" back to the Comsol interface.
Good luck!
********************************
function resultfem=remove_internal_boundaries(fem)
%this function removes internal boundaries from a fem strukture and keeps the mesh
%fem=remove_internal_boundaries(fem)
%delete interior boundaries of geometry--------------------------------------------------------------------------------
new_geometry=geomdel(fem.geom);
%geomplot(new_geometry);
%read mesh information from fem----------------------------------------------------------------------------------------
el=get(fem.mesh,'el');
p=get(fem.mesh,'p');
%write triangle element information to new el structure----------------------------------------------------------------
for i=1:length(el)
if isequal(el{i}.type,'tri')
tri_elem=el{i}.elem;
end
end
el_structure{1}=struct('type','tri','elem',tri_elem);
%create new mesh ------------------------------------------------------------------------------------------------------
fem.mesh=femmesh(p,el_structure);
fem.mesh=meshenrich(fem);
%the new mesh has to be modified to fit the already existing geometry==================================================
%read new mesh information from fem------------------------------------------------------------------------------------
clear el; clear p;
el=get(fem.mesh,'el');
p=get(fem.mesh,'p');
tri=el{1};
vtx=el{2};
edg=el{3}
%correct vtx information-----------------------------------------------------------------------------------------------
%get elem vector
elem=vtx.elem;
%get according coordinates
elem_coord=p(:,elem)';
[n m] = size(elem_coord);
%get according dom numbers
for k = 1:n
vtx.dom(k)=get_point(new_geometry, elem_coord(k,1),elem_coord(k,2));
end
%correct edg information-----------------------------------------------------------------------------------------------
%get elem vector
elem=edg.elem;
%get according coordinates
elem_coord_1=p(:,elem(1,:))';
elem_coord_2=p(:,elem(2,:))';
[n m] = size(elem_coord_1);
for k = 1:n
%get according dom numbers
x1=elem_coord_1(k,1);
y1=elem_coord_1(k,2);
xy1=[x1 y1];
x2=elem_coord_2(k,1);
y2=elem_coord_2(k,2);
xy2=[x2 y2];
edg.dom(k)=get_edg_boundary(new_geometry, xy1, xy2);
%calculate up-down subdomains
%calculate test point that lies left of boundary
epsi=3*eps;
if ~(abs(x2-x1)<epsi)
test_point_x=x1+(x2-x1)/2;
if x2-x1 > 0
test_point_y=y1+(y2-y1)/2+epsi;
else
test_point_y=y1+(y2-y1)/2-epsi;
end
elseif ~(abs(y2-y1)<epsi)
test_point_y=y1+(y2-y1)/2;
if y2-y1 > 0
test_point_x=x1+(x2-x1)/2-epsi;
else
test_point_x=x1+(x2-x1)/2+epsi;
end
else
msgbox('Error in mesh correction.');
end
%test if test point lies inside the subdomain polygon and set ud numbers
%create convex polygon
poly_ind=convhull(p(1,:),p(2,:));
poly_p_x=p(1,poly_ind);
poly_p_y=p(2,poly_ind);
%test and set ud number
edg.ud(1,k)=inpolygon(test_point_x,test_point_y,poly_p_x,poly_p_y);
edg.ud(2,k)=~edg.ud(1,k);
%transform param values from absolute distances to relative distances
%get length of boundary
XY1=flgeomed(new_geometry,edg.dom(k),0);
XY2=flgeomed(new_geometry,edg.dom(k),1);
bound_length=sqrt((XY2(2)-XY1(2))^2+(XY2(1)-XY1(1))^2);
%set param values
edg.param(:,k)=edg.param(:,k)/bound_length;
%check orientation and flip, if edg orientation is not equal boundary orientation
if ~and(isequal(XY2(1)-XY1(1)>epsi,x2-x1>epsi),isequal(XY2(2)-XY1(2)>epsi,y2-y1>epsi))
%flip elem
saveelem=edg.elem(1,k);
edg.elem(1,k)=edg.elem(2,k);
edg.elem(2,k)=saveelem;
%flip ud
saveud=edg.ud(1,k);
edg.ud(1,k)=edg.ud(2,k);
edg.ud(2,k)=saveud;
%calculate new param
edg.param(1,k)=1-edg.param(1,k);
edg.param(2,k)=1-edg.param(2,k);
end
end
%assign corrected mesh information-------------------------------------------------------------------------------------
el{1}=tri;
el{2}=edg;
el{3}=vtx;
fem.mesh=femmesh(p,el);
%assign new geometry---------------------------------------------------------------------------------------------------
fem.geom=new_geometry;
resultfem=fem;
end
************************************
function index = get_point(geometry,x,y,tol)
%This function finds the index of a point at given coordinates with tolerance tol
%index = get_point(geometry,x,y,tol)
%set default tolerance=================================================================================================
if nargin < 4
tol = eps;
end
% plot geometry =======================================================================================================
%geomplot(geometry,'pointlabels','on','edgelabels','on');
%get number of objects=================================================================================================
gd = geominfo(geometry,'out',{'gd'});
no = geominfo(geometry,'out',{'no'},'od',0:gd);
%get vertex coordinates================================================================================================
xy=flgeomvtx(geometry);
%get indice that lie in the region of interest=========================================================================
% getting elements with x-coordinate > x-tol
element_x_g = find(xy(1,:) >= x - tol);
% getting elements with x-coordinate < x+tol
element_x_s = find(xy(1,:) <= x + tol);
% creating a matrix for the elements greater x
coordinate_matrix_x_g = zeros(1,no(1));
% creating a matrix for the elements smaller x
coordinate_matrix_x_s = zeros(1,no(1));
% filling the matrix with a one when element fullfills the condition > x
coordinate_matrix_x_g(element_x_g) = 1;
% filling the matrix with a one when element fullfills the condition < x
coordinate_matrix_x_s(element_x_s) = 1;
% Merge the x-coordinate_s and x-coordinate_g matrix
coordinate_matrix_x = coordinate_matrix_x_g & coordinate_matrix_x_s;
% getting elements with y-coordinate > y-tol
element_y_g = find(xy(2,:) >= y - tol);
% getting elements with y-coordinate < y + tol
element_y_s = find(xy(2,:) <= y + tol);
% creating a matrix for the elements greater y
coordinate_matrix_y_g = zeros(1,no(1));
% creating a matrix for the elements smaller y
coordinate_matrix_y_s = zeros(1,no(1));
% filling the matrix with an one when element fullfills the condition > y
coordinate_matrix_y_g(element_y_g) = 1;
% filling the matrix with an one when element fullfills the condition < y
coordinate_matrix_y_s(element_y_s) = 1;
% Merge the y-coordinate_s and y-coordinate_g matrix
coordinate_matrix_y = coordinate_matrix_y_g & coordinate_matrix_y_s;
%% Calculating the Object which fullfills all the conditions x y
%get indice
index = find(coordinate_matrix_x & coordinate_matrix_y == 1);
if length(index) > 1
msgbox(['More than one point found in region around x = ' num2str(x,3) ', y = ' num2str(y,3) ],'Error','error');
end
if length(index) < 1
msgbox(['No point found in region around x = ' num2str(x,3) ', y = ' num2str(y,3) ],'Error','error');
end
end
****************************************
function index = get_edg_boundary(geometry,p1,p2,tol)
%this function finds the boundary index of a edge element between the
%points p1 = [x1 y1] and p2 =[x2 y2]
%index = get_edg_boundary(geometry,p1,p2)
%set default tolerance=================================================================================================
if nargin < 4
tol = eps;
end
% plot geometry =======================================================================================================
%geomplot(geometry,'pointlabels','on','edgelabels','on');
%get number of objects=================================================================================================
gd = geominfo(geometry,'out',{'gd'});
no = geominfo(geometry,'out',{'no'},'od',0:gd);
%get coordinates of edges==============================================================================================
X1=0;
Y1=0;
X2=0;
Y2=0;
for k = 1:no
xy=flgeomed(geometry,k,0);
X1(k)=xy(1);
Y1(k)=xy(2);
xy2=flgeomed(geometry,k,1);
X2(k)=xy2(1);
Y2(k)=xy2(2);
end
%%calculate all boundary elements that may include the edg element in x-direction
% getting elements with X1 <= x1, X1 <= x2
element_x_s1 = find(X1 <= p1(1)+tol);
element_x_s2 = find(X1 <= p2(1)+tol);
% getting elements with X2 >= x1, X2 >=x2
element_x_g1 = find(X2 >= p1(1)-tol);
element_x_g2 = find(X2 >= p2(1)-tol);
% creating matrix for start_x smaller x_vals
coordinate_matrix_x_s1 = zeros(1,no(1));
coordinate_matrix_x_s2 = zeros(1,no(1));
% creating matrix for end_x greater x_vals
coordinate_matrix_x_g1 = zeros(1,no(1));
coordinate_matrix_x_g2 = zeros(1,no(1));
% filling matrix with a one when element fullfills the smaller condition
coordinate_matrix_x_s1(element_x_s1) = 1;
coordinate_matrix_x_s2(element_x_s2) = 1;
coordinate_matrix_x_s = coordinate_matrix_x_s1 & coordinate_matrix_x_s2;
% filling matrix with a one when element fullfills the greater condition
coordinate_matrix_x_g1(element_x_g1) = 1;
coordinate_matrix_x_g2(element_x_g2) = 1;
coordinate_matrix_x_g = coordinate_matrix_x_g1 & coordinate_matrix_x_g2;
% Merge the x-coordinate_s and x-coordinate_g matrix
coordinate_matrix_x = coordinate_matrix_x_g & coordinate_matrix_x_s;
%% calculate all boundary elements that may include the edg element in y-direction
% getting elements with Y1 <= y1, Y1 <= y2
element_y_s1 = find(Y1 <= p1(2)+tol);
element_y_s2 = find(Y1 <= p2(2)+tol);
% getting elements with Y2 >= x1, Y2 >=x2
element_y_g1 = find(Y2 >= p1(2)-tol);
element_y_g2 = find(Y2 >= p2(2)-tol);
% creating matrix for start_y smaller y_vals
coordinate_matrix_y_s1 = zeros(1,no(1));
coordinate_matrix_y_s2 = zeros(1,no(1));
% creating matrix for end_x greater x_vals
coordinate_matrix_y_g1 = zeros(1,no(1));
coordinate_matrix_y_g2 = zeros(1,no(1));
% filling matrix with a one when element fullfills the smaller condition
coordinate_matrix_y_s1(element_y_s1) = 1;
coordinate_matrix_y_s2(element_y_s2) = 1;
% filling matrix with a one when element fullfills the greater condition
coordinate_matrix_y_g1(element_y_g1) = 1;
coordinate_matrix_y_g2(element_y_g2) = 1;
% Merge the x-coordinate_s and x-coordinate_g matrix
coordinate_matrix_y_g = coordinate_matrix_y_g1 & coordinate_matrix_y_g2;
coordinate_matrix_y_s = coordinate_matrix_y_s1 & coordinate_matrix_y_s2;
coordinate_matrix_y = coordinate_matrix_y_g & coordinate_matrix_y_s;
%% Calculating the Object which fullfills all the conditions
% Addition of both matrices to get the element which is the searchobject
index = find(coordinate_matrix_x & coordinate_matrix_y == 1);
if length(index) > 1
msgbox(['Error: More than one possible boundary found.' sprintf('\n') ...
'for the edg element between p1 = (' num2str(p1(1),3) ', ' num2str(p1(2),3) ') and' sprintf('\n') ...
' p2 = (' num2str(p2(1),3) ', ' num2str(p2(2),3) ') !'],'Error','error');
end
if length(index) < 1
msgbox(['Error: No boundary found for the edg element' sprintf('\n') ...
'between p1 = (' num2str(p1(1),3) ', ' num2str(p1(2),3) ') and' sprintf('\n') ...
' p2 = (' num2str(p2(1),3) ', ' num2str(p2(2),3) ') !'],'Error','error');
end
end
Attachments:
Please login with a confirmed email address before reporting spam
Well why do you really want to remove the interiour boundaries, just leave them, no ?
As the mesh is related to your geometry there is no easy way around, from my knowledge you can only export the mesh as is and import it again, but then you loose the ability to easily play with it
But OK you have given us some interesting commands and scripts there, thanks for that !
Good luck
Ivar
Note that while COMSOL employees may participate in the discussion forum, COMSOL® software users who are on-subscription should submit their questions via the Support Center for a more comprehensive response from the Technical Support team.