diff --git a/TestKRTFparallel.m b/TestKRTFparallel.m index f5199c4f..47ca3f87 100755 --- a/TestKRTFparallel.m +++ b/TestKRTFparallel.m @@ -1,23 +1,93 @@ -load PlotFile + +%% +clc +load TestSaveuvhAssembly tic -[K,R,T,F]=KRTF(s,S,B,h,u,v,AGlen,n,C,m,coordinates,connectivity,Boundary,nip,alpha,rho,rhow,g,CtrlVar); + +for Iint=1:MUA.nip + + + [Tx1,Fx1,Ty1,Fy1,Th1,Fh1,Kxu1,Kxv1,Kyu1,Kyv1,Kxh1,Kyh1,Khu1,Khv1,Khh1]=... + uvhAssemblyIntPointImplicitSUPG(Iint,ndim,MUA,... + bnod,hnod,unod,vnod,AGlennod,nnod,Cnod,mnod,h0nod,u0nod,v0nod,as0nod,ab0nod,as1nod,ab1nod,dadhnod,Bnod,Snod,rhonod,... + uonod,vonod,Conod,monod,uanod,vanod,Canod,manod,... + CtrlVar,rhow,g,Ronly,ca,sa,dt,... + Tx0,Fx0,Ty0,Fy0,Th0,Fh0,Kxu0,Kxv0,Kyu0,Kyv0,Kxh0,Kyh0,Khu0,Khv0,Khh0); + + Tx=Tx+Tx1; Fx=Fx+Fx1; + Ty=Ty+Ty1; Fy=Fy+Fy1; + Th=Th+Th1; Fh=Fh+Fh1; + + Kxu=Kxu+Kxu1; Kxv=Kxv+Kxv1; + Kyu=Kyu+Kyu1; Kyv=Kyv+Kyv1; + Kxh=Kxh+Kxh1; Kyh=Kyh+Kyh1; + Khu=Khu+Khu1; Khv=Khv+Khv1; Khh=Khh+Khh1; + +end toc -Nnodes=max(connectivity(:)); [Nele,nod]=size(connectivity); +tic + +parfor Iint=1:MUA.nip + + + [Tx1,Fx1,Ty1,Fy1,Th1,Fh1,Kxu1,Kxv1,Kyu1,Kyv1,Kxh1,Kyh1,Khu1,Khv1,Khh1]=... + uvhAssemblyIntPointImplicitSUPG(Iint,ndim,MUA,... + bnod,hnod,unod,vnod,AGlennod,nnod,Cnod,mnod,h0nod,u0nod,v0nod,as0nod,ab0nod,as1nod,ab1nod,dadhnod,Bnod,Snod,rhonod,... + uonod,vonod,Conod,monod,uanod,vanod,Canod,manod,... + CtrlVar,rhow,g,Ronly,ca,sa,dt,... + Tx0,Fx0,Ty0,Fy0,Th0,Fh0,Kxu0,Kxv0,Kyu0,Kyv0,Kxh0,Kyh0,Khu0,Khv0,Khh0); + + Tx=Tx+Tx1; Fx=Fx+Fx1; + Ty=Ty+Ty1; Fy=Fy+Fy1; + Th=Th+Th1; Fh=Fh+Fh1; + + Kxu=Kxu+Kxu1; Kxv=Kxv+Kxv1; + Kyu=Kyu+Kyu1; Kyv=Kyv+Kyv1; + Kxh=Kxh+Kxh1; Kyh=Kyh+Kyh1; + Khu=Khu+Khu1; Khv=Khv+Khv1; Khh=Khh+Khh1; + +end +toc + -FEmesh.Coordinates=coordinates; -FEmesh.Connectivity=connectivity; -FEmesh.Boundary=Boundary; -FEmesh.Nnodes=Nnodes; -FEmesh.Nele=Nele; -FEmesh.Nod=nod; -FEmesh.Nip=nip; +%% +N=10000; +A=rand(N,N); +B=rand(N,N); +%% +clc tic -parfor Iint=1:nip; - [Ktest{Iint},R,T,F]=KRTFparInt(Iint,s,S,B,h,u,v,AGlen,n,C,m,FEmesh,alpha,rho,rhow,g,CtrlVar); -end +AA=distributed(A); +BB=distributed(B); toc +tic +C=TestAddM(A,B); +t=toc; +trace(C) + +tic + + CC=TestAddM(AA,BB); + +tspmd=toc; +trace(CC) + +fprintf('t=%f \t tspmd=%f \n',t,tspmd) + + + + + + + + + + + + + diff --git a/TestuvhAssembly.m b/TestuvhAssembly.m new file mode 100644 index 00000000..25a5a0a3 --- /dev/null +++ b/TestuvhAssembly.m @@ -0,0 +1,68 @@ +delete(gcp('nocreate')) +poolobj=parpool('local',6); + +%% +poolobj = gcp('nocreate'); + + +%clc +fprintf('\n\n\n\n') +%load uvhAssembly.mat +load TestSaveuvhAssembly + + + +CtrlVar.Parallel.uvhAssembly.parfor=0; +tic +[UserVar,RunInfo,R,K,Tint,Fext]=uvhAssembly(UserVar,RunInfo,CtrlVar,MUA,F0,F1,ZeroFields); +toc +fprintf(' sum(R)=%g \t trace(K)=%g \n',full(sum(R)),full(trace(K))) + +% The spmd option has potential + +CtrlVar.NumWorkers=poolobj.NumWorkers; +fprintf(' Number of workers=%i \n ',CtrlVar.NumWorkers) +tic +[UserVar,RunInfo,R,K,Tint,Fext]=uvhAssemblySPMD(UserVar,RunInfo,CtrlVar,MUA,F0,F1,ZeroFields); +toc +fprintf(' sum(R)=%g \t trace(K)=%g \n',full(sum(R)),full(trace(K))) + +%% The parfor option is not good and apparantly always slower + + +nW=poolobj.NumWorkers; +N=ceil(MUA.Nele/nW) ; + +i1=1 ; i2=N; + +for I=1:nW + + Partition{I}=[i1:i2] ; + i1=i2+1 ; + i2=min([i2+N,MUA.Nele]); +end + +% using parfor +neq=3*MUA.Nnodes; +R=sparseUA(neq,1); +K=sparseUA(neq,neq); + +tic +parfor iWorker=1:numel(Partition) + + M{iWorker}=MUA; + M{iWorker}.connectivity=MUA.connectivity(Partition{iWorker},:); + M{iWorker}.Nele=numel(Partition{iWorker}); + M{iWorker}.Deriv=MUA.Deriv(Partition{iWorker},:,:,:); + M{iWorker}.DetJ=MUA.DetJ(Partition{iWorker},:); + [~,~,r,k,Tint,Fext]=uvhAssembly(UserVar,RunInfo,CtrlVar,M{iWorker},F0,F1,ZeroFields); + R=R+r ; + K=K+k; + +end +toc + + + + + diff --git a/Ua2D_DefaultParameters.m b/Ua2D_DefaultParameters.m index dbf8b8b2..34c696d7 100755 --- a/Ua2D_DefaultParameters.m +++ b/Ua2D_DefaultParameters.m @@ -1483,7 +1483,11 @@ % % Consult the matlab manual for further information % -CtrlVar.ParallelAssembly=1; +CtrlVar.Parallel.uvhAssembly.parfor=1; +CtrlVar.Parallel.uvhAssembly.spmd=1; + + + %% Tracers CtrlVar.Tracer.SUPG.Use=1; CtrlVar.Tracer.SUPG.tau='taus' ; % {'tau1','tau2','taus','taut'} diff --git a/UaUtilities/distFig.m b/UaUtilities/distFig.m new file mode 100644 index 00000000..115787c0 --- /dev/null +++ b/UaUtilities/distFig.m @@ -0,0 +1,831 @@ +function distFig(varargin) +% ===== Syntax ============================================================ +% distFig(...,'Screen',Value) +% distFig(...,'Position',Value) +% +% distFig(...,'Rows',Value) +% distFig(...,'Columns',Value) +% +% distFig(...,'Not',Value) +% distFig(...,'Only',Value) +% distFig(...,'Offset',Value) +% +% distFig(...,'Adjust',Value) +% distFig(...,'Extra',Value) +% distFig(...,'Menu',Value) +% distFig(...,'Transpose',Value) +% distFig(...,'Simulink',Value) +% distFig(...,'Tight',Value) +% distFig(...,'Scale',Value) +% distFig(...,'ScaleOrigin',Value) +% distFig(...,'FreezeSize',Value) +% distFig(...,'Order',Value) +% +% ===== Description ======================================================= +% distFig(...,'Screen',Value) assigns where the figures will be +% distributed. +% Synonyms for 'Screen' are 'Scr' and 'S'. Value can be: +% 'C' / 'Center' (Default) +% 'W' / 'West' / 'L' / 'Left' +% 'E' / 'East' / 'R' / 'Right' +% 'N' / 'North' / 'T' / 'Top' +% 'S' / 'South' / 'B' / 'Bottom' +% 'Main' / 'Primary' +% 'Ext' / 'External' / 'Secondary' +% +% distFig(...,'Position',Value) assigns in which part of the screen the +% figures will be distributed. +% Synonyms for 'Position' are 'Pos' and 'P'. Value can be: +% 'C' / 'Center' (Default) +% 'W' / 'West' / 'L' / 'Left' +% 'E' / 'East' / 'R' / 'Right' +% 'N' / 'North' / 'T' / 'Top' +% 'S' / 'South' / 'B' / 'Bottom' +% 'NW' +% 'NE' +% 'SW' +% 'SE' +% +% distFig(...,'Rows',Value) assigns how many rows the figures will be +% distributed on. +% Synonyms for 'Rows' are 'R'. Value can be: +% 1...n +% 'Auto' / -1 +% 'Auto' indicates that it automatically calculates the number of required +% rows. +% +% distFig(...,'Columns',Value) assigns how many rows the figures will be +% distributed on. +% Synonyms for 'Columns' are 'Cols' and 'C'. Value can be: +% 1...n +% 'Auto' / -1 +% 'Auto' indicates that it automatically calculates the number of required +% columns. +% +% distFig(...,'Not',Value) excludes specified figures from the distribution +% list. Value must be an array with the excluded figure numbers. The +% default value is []. The input argument 'gcf' (get current figure) can be +% used as well. +% +% distFig(...,'Only',Value) does only distribute specified figures. Value +% must be an array with the figure which will be distributed. The +% default value is []. The input argument 'gcf' (get current figure) can be +% used as well. +% +% distFig(...,'Offset',Value) can be used to shift all figures on the +% distribution list. Synonyms for 'Offset' is 'O'. Value must be an integer +% larger or equal to zero. The default offset value is 0. +% +% distFig(...,'Adjust',Value) can be used to adjust all figure positions. +% For instance, if all figures should be moved 20 pixels to the right, +% which is not possible with the other features, Value should be [20,0]. +% If Value is below 1, the scalars indicate the relative adjustment to the +% screen. If the selected monitor is [1920,1080] pixels, a Values of +% [0.25,-0.5] moves all figures with [480,540] pixels. +% Synonyms for 'Ajust' is 'A'. Value can be: +% [Integer,Integer] (In order to adjust by a specific ammount) +% [Scalar,Scalar]( < 1) (To adjust a relative ammount of the monitor size) +% The default value is [0,0]. +% +% distFig(...,'Extra',Value) is used to handle the extra figures, which +% might not fit into 'Rows' * 'Cols'. For instance, 5 figure are to be +% distributed on a 2x2 = 4 area. The fifth figure is then places on top of +% the first figure if 'Extra' is 'restart'. It can be ignored by setting +% 'Extra' to 'ignore', in which the fifth figure will not be distributed. +% +% distFig(...,'Menu',Value) can be used to modify the menu bar. +% Value can be: +% 'figure' +% 'none' +% +% distFig(...,'Transpose',Value) can be used to tranpose the order of +% distributing. The values must be logical and the default value is false. +% +% distFig(...,'Simulink',Value) can be used to handle simulink figures. +% Value can be: +% 'include' (Default) +% 'exclude' +% 'only' +% If value is true, simulink figures will be distributed along with the +% other figures. If value if 'exclude' simulink figures will be +% excluded from the distribution list. If value is 'only', only the +% simulink figures will be distributed and not the ordinary figures. +% +% distFig(...,'Tight',Value) can be used to stretch the figure to the +% border of the figure, so no unnecessary "whitespace" is present. +% Value must be logical and the default value if false. +% +% distFig(...,'Scale',Value) can be used to scale the figure matrix. Both +% horizontal and vertical scaling can be applied, but also similar scaling. +% Value is a single scalar for similar scaling, but is a 2x1 matrix for +% specific scaling in each direction. For instance, distFig('Scale',0.5) +% scales all figures by 50% relative to the upper left corner of the +% distribution area (Default Scale-origin). distFig('Scale',[0.8,0.4]) +% scales the figures by 80% and 40% in the horizontal and vertical +% directions respectivly relative to the default scale-origin. +% +% distFig(...,'ScaleOrigin',Value) can be used in combination with the +% 'Scale' option. Value is a 2x1 matrix with the origin. If these values +% are between 0 and 1 the relative monitor size is used, whereas larger +% values should be rounded indicating pixel values. For instance, +% distFig('Scale',0.5,'ScaleOrigin',[0.5,1]) scales the figures relative +% to the midpoint on the right hand side of the selected monitor. For a +% monitor with resolution 1920x1080, this would be equal to +% distFig('Scale',0.5,'ScaleOrigin',[1920,960]). +% The default scale origin is in the upper left corner of the distribution +% area. +% Synonyms for 'ScaleOrigin' are 'Origin', 'Orig' and 'Scaleorig'. +% +% distFig(...,'FreezeSize',Value) can be used to freeze the sizes of the +% figures before distribution. Currently, this function anchors the figures +% to the upper left corner of the original position, yet keeping the +% original size - it does not calculate new positions, so the figures may +% overlap. +% Synonym for 'FreezeSize' is 'Freeze'. +% +% distFig(...,'Order',Value) can be used to control the plotting order. For +% instance, distFig('Only',[5,6,7,8],'Order',[2,1,4,3]) will plot figure +% 5,6,7 and 8 in the order of 6,5,8 and 7. The ordering argument is thus +% related to the input of 'Only'. +% +% ===== Examples ========================================================== +% distFig(); +% This will distribute all open figures on the primary screen in two rows. +% +% distFig('Screen','Left','Position','Right','Only',[1,2,4]) +% This will only distribute figure 1, 2 and 4 on the right part of the left +% screen. +% +% distFig('Offset',2,'Not',[1,2]) +% This will distribute all figure but figure 1 and 2 in the same pattern as +% distFig(), but figure 1 and 2 will not be distributed, but instead there will +% be blank spots where they would have been distributed. +% +% ===== Note ============================================================== +% If you find any errors or bugs with this version please contact me on +% AndersSSimonsen@GMail.com or write a comment on file exchange - then I'll +% take a look at it. :) +% +% This function will only work in MATLAB 2014b and onwards due to the +% massive overhaul in the figure handle system - I will not support +% previous versions. + +% ========================================================================= +% ===== Version =========================================================== +% ========================================================================= + +% Anders Schou Simonsen, AndersSSimonsen@GMail.com +% Version 5.5 +% 31/03-2015 + +% ========================================================================= +% ===== Default values ==================================================== +% ========================================================================= + +Rows = -1; +Cols = -1; +Scr = 'C'; +Pos = 'C'; +Tight = false; +Menu = ''; +Transpose = false; +Extra = 'restart'; +Offset = 0; +Not = []; +Only = []; +Simulink = 'include'; +Adjust = [0,0]; +Scale = 1; +Scale_Orig = []; +FreezeSize = false; +Order = []; + +% ========================================================================= +% ===== Get inputs ======================================================== +% ========================================================================= + +if (mod(nargin,2) ~= 0) + error('Uneven number of inputs! Returning...'); +end + +for i = 1:2:nargin + if (ischar(varargin{i+1})) + varargin{i+1} = lower(varargin{i+1}); + end + switch lower(varargin{i}) + case {'scr','screen','s'} + % ============================================================= + Allow = { + 'C' 'c' 'center' 'main' 'primary' + 'W' 'w' 'west' 'l' 'left' + 'E' 'e' 'east' 'r' 'right' + 'N' 'n' 'north' 't' 'top' + 'S' 's' 'south' 'b' 'bottom' + 'Ext' 'ext' 'external' 'secondary' NaN + }; + Trigger = any(strcmp(Allow,varargin{i+1}),2); + if (~any(Trigger)) + warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i}); + else + Scr = Allow{Trigger,1}; + end + case {'pos','position','p'} + % ============================================================= + Allow = { + 'C' 'c' 'center' NaN NaN + 'W' 'w' 'west' 'l' 'left' + 'E' 'e' 'east' 'r' 'right' + 'N' 'n' 'north' 't' 'top' + 'S' 's' 'south' 'b' 'bottom' + 'NW' 'nw' NaN NaN NaN + 'NE' 'ne' NaN NaN NaN + 'SW' 'sw' NaN NaN NaN + 'SE' 'se' NaN NaN NaN + }; + Trigger = any(strcmp(Allow,varargin{i+1}),2); + if (~any(Trigger)) + warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i}); + else + Pos = Allow{Trigger,1}; + end + case {'rows','r'} + % ============================================================= + if (strcmp(varargin{i+1},'auto')) + Rows = -1; + else + if ~((isnumeric(varargin{i+1})) && (mod(varargin{i+1},1) == 0)) + warning('Input to ''%s'' must be a round numeric value!',varargin{i}); + else + Rows = varargin{i+1}; + end + end + case {'cols','columns','c'} + % ============================================================= + if (strcmp(varargin{i+1},'auto')) + Cols = -1; + else + if ~((isnumeric(varargin{i+1})) && (mod(varargin{i+1},1) == 0)) + warning('Input to ''%s'' must be a round numeric value!',varargin{i}); + else + Cols = varargin{i+1}; + end + end + case {'ext','extra'} + % ============================================================= + Allow = { + 'ignore' + 'restart' + }; + Trigger = any(strcmp(Allow,varargin{i+1}),2); + if (~any(Trigger)) + warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i}); + else + Extra = Allow{Trigger,1}; + end + case {'menu','bar'} + % ============================================================= + Allow = { + 'figure' + 'none' + }; + Trigger = any(strcmp(Allow,varargin{i+1}),2); + if (~any(Trigger)) + warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i}); + else + Menu = Allow{Trigger,1}; + end + case {'transpose'} + % ============================================================= + if (~islogical(varargin{i+1})) + warning('Input to ''%s'' must be logical!',varargin{i}); + else + Transpose = varargin{i+1}; + end + case {'offset','o'} + % ============================================================= + if ~((isnumeric(varargin{i+1})) && (mod(varargin{i+1},1) == 0)) + warning('Input to ''%s'' must be a round numeric value!',varargin{i}); + else + Offset = varargin{i+1}; + end + case {'adjust','a'} + % ============================================================= + if ~(isnumeric(varargin{i+1})) + warning('Input to ''%s'' must be numeric!',varargin{i}); + elseif (numel(varargin{i+1}) ~= 2) + warning('Input to ''%s'' must be a (1 x 2) matrix with integers or scalars less than one!',varargin{i}); + elseif (all(mod(varargin{i+1},1) == 0)) + Adjust = varargin{i+1}; + else + if (any(varargin{i+1} > 1)) + warning('Input to ''%s'' must be either integers or scalars less than one!',varargin{i}); + else + Adjust = varargin{i+1}; + end + end + case {'not'} + % ============================================================= + if ~((isnumeric(varargin{i+1}) && all(mod(varargin{i+1},1) == 0)) || isobject(varargin{i+1})) + warning('Input to ''%s'' must be round numeric values!',varargin{i}); + else + if (isobject(varargin{i+1})) + Not = get(varargin{i+1},'Number'); + if (iscell(Not)) + Not = cell2mat(Not); + end + else + Not = varargin{i+1}; + end + end + case {'only'} + % ============================================================= + if ~((isnumeric(varargin{i+1}) && all(mod(varargin{i+1},1) == 0)) || isobject(varargin{i+1})) + warning('Input to ''%s'' must be round numeric values!',varargin{i}); + else + if (isobject(varargin{i+1})) + Only = get(varargin{i+1},'Number'); + if (iscell(Only)) + Only = cell2mat(Only); + end + else + Only = varargin{i+1}; + end + end + case {'simu','simulink'} + % ============================================================= + Allow = { + 'include' NaN + 'exclude' 'ignore' + 'only' NaN + }; + Trigger = any(strcmp(Allow,varargin{i+1}),2); + if (~any(Trigger)) + warning('Input ''%s'' not recognized for ''%s''!',varargin{i+1},varargin{i}); + else + Simulink = Allow{Trigger,1}; + end + case {'tight'} + % ============================================================= + if (~islogical(varargin{i+1})) + warning('Input to ''%s'' must be logical!',varargin{i}); + else + Tight = varargin{i+1}; + end + case {'scale'} + % ============================================================= + if (~isnumeric(varargin{i+1}) || (numel(varargin{i+1}) > 2)) + warning('Input to ''%s'' must be one or two numeric values (x and y scale)!',varargin{i}); + else + Scale = varargin{i+1}; + end + case {'origin','orig','scaleorig','scaleorigin'} + % ============================================================= + if (~isnumeric(varargin{i+1}) || (numel(varargin{i+1}) ~= 2)) + warning('Input to ''%s'' must be two numeric values (x0 and y0)!',varargin{i}); + else + Scale_Orig = varargin{i+1}; + end + case {'freezesize','freeze'} + % ============================================================= + if (~islogical(varargin{i+1})) + warning('Input to ''%s'' must be logical!',varargin{i}); + else + FreezeSize = varargin{i+1}; + end + case {'order'} + % ============================================================= + if ~(isnumeric(varargin{i+1}) && all(mod(varargin{i+1},1) == 0)) + warning('Input to ''%s'' must be round numeric values!',varargin{i}); + else + Order = varargin{i+1}; + end + otherwise + % ============================================================= + fprintf('Input ''%s'' not recognized!',varargin{i}); + end +end + +% ========================================================================= +% ===== Constants ========================================================= +% ========================================================================= + +% ===== Limits ============================================================ +Limits = {... + 'C' [0,1] [0,1] + 'W' [0,0.5] [0,1] + 'E' [0.5,1] [0,1] + 'N' [0,1] [0.5,1] + 'NW' [0,0.5] [0.5,1] + 'NE' [0.5,1] [0.5,1] + 'S' [0,1] [0,0.5] + 'SW' [0,0.5] [0,0.5] + 'SE' [0.5,1] [0,0.5] + }; + +% ===== Screen angles ===================================================== +Screens = {... + (-pi * 1 / 4) (+pi * 1 / 4) 'E' + (-pi * 3 / 4) (-pi * 1 / 4) 'S' + (+pi * 1 / 4) (+pi * 3 / 4) 'N' + (+pi * 3 / 4) Inf 'W' + -Inf (-pi * 3 / 4) 'W' + }; + +% ===== Taskbar height ==================================================== +Taskbar_Height = 40; + +% ========================================================================= +% ===== Figure list ======================================================= +% ========================================================================= + +% ===== All figures ======================================================= +Fig_Object = findall(0,'type','figure'); +if (isempty(Fig_Object)) + fprintf('distFig: No figures to distribute!\n'); + return; +end + +% ===== Remove not visible figures ======================================== +Visible = arrayfun(@(n) (strcmp(get(Fig_Object(n),'Visible'),'on')),1:numel(Fig_Object)); +Fig_Object = Fig_Object(Visible); + +% ===== Include simulink figures ========================================== +Fig_Number = {Fig_Object.Number}; +Empty = arrayfun(@(n) (isempty(Fig_Number{n})),1:numel(Fig_Number)); +Fig_Number(Empty) = {0}; +Fig_Number = cell2mat(Fig_Number); +[~,Index] = sort(get(Fig_Object(Fig_Number == 0),'Name')); +Temp = find(Fig_Number == 0); +Fig_Number(Temp(Index)) = -(numel(Index):(-1):1); + +% ===== Logical distribution array ======================================== +Fig_Dist = true(1,numel(Fig_Object)); + +% ===== Simulink figures ================================================== +if strcmp(Simulink,'exclude') + Fig_Dist = (Fig_Number > 0); +end +if strcmp(Simulink,'only') + Fig_Dist = (Fig_Number < 0); +end + +% ===== Not =============================================================== +Fig_Dist(ismember(Fig_Number,Not)) = false; + +% ===== Only ============================================================== +if (~isempty(Only)) + Fig_Dist(~ismember(Fig_Number,Only)) = false; +end + +% ===== Number of figures ================================================= +nFig_Dist = sum(Fig_Dist); + +% ===== Return ============================================================ +if (nFig_Dist == 0) + return; +end + +% ========================================================================= +% ===== Monitor =========================================================== +% ========================================================================= + +% ===== Get monitor positions ============================================= +Monitors = get(0,'MonitorPositions'); +Monitors_Center = Monitors(:,1:2) + Monitors(:,3:4) / 2; +Monitors_Label = cell(size(Monitors,1),1); + +% ===== Center monitor ==================================================== +Temp = sum(abs(Monitors(:,1:2) - 1),2); +Trigger_C = find(Temp == min(Temp)); +Monitors_Label{Trigger_C} = 'C'; + +% ===== External monitors ================================================= +Dir = Monitors_Center - repmat(Monitors_Center(Trigger_C,:),size(Monitors_Center,1),1); +Theta = atan2(Dir(:,2),Dir(:,1)); +for i = 1:numel(Theta) + if (i ~= Trigger_C) + Monitors_Label{i} = Screens{(Theta(i) > [Screens{:,1}]) & (Theta(i) <= [Screens{:,2}]),3}; + end +end + +% ===== Select monitor ==================================================== +Monitor = Monitors(strcmp(Monitors_Label,Scr),:); +if (isempty(Monitor)) + if (strcmp(Scr,'Ext')) + if (size(Monitors,1) == 1) + warning('No external monitor could be found!'); + Monitor = Monitors(1,:); + else + Monitor = Monitors(find(~strcmp(Monitors_Label,'C'),1,'first'),:); + end + else + warning(['Screen ''%s'' could not be found! (Using ''C'' instead)\nThe following monitors were identified: %s.\n'... + 'If the function cannot find the monitor try and restart MATLAB - this will reset the monitor-matrix, which is being used by the function.'],... + Scr,sprintf('%s\b\b\b\b\b',sprintf('''%s'' and ',Monitors_Label{:}))); + Monitor = Monitors(strcmp(Monitors_Label,'C'),:); + if (isempty(Monitor)) + warning(['distFig cannot find matching monitors - using the first one!',... + '\nPlease report this problem to AndersSSimonsen@GMail.com, where you include this matrix:'],0); + disp(Monitors); + Monitor = Monitors(1,:); + end + end +end + +% ========================================================================= +% ===== Rows and columns ================================================== +% ========================================================================= + +Limit = Limits(strcmp(Limits(:,1),Pos),:); +if ((Rows == (-1)) && (Cols == (-1))) + AR_Ideal = 1.2; + AR_Mean = Inf; + for i = 1:50 + % ===== Exception ================================================= + if ((nFig_Dist + Offset) == 4) + Rows = 2; + Cols = 2; + break; + end + + % ===== Temporary rows and columns ================================ + Rows = i; + Cols = ceil((nFig_Dist + Offset) / Rows); + + % ===== Sizes ===================================================== + x = round(linspace(Limit{2}(1),Limit{2}(2),Cols + 1) * Monitor(3)) + 1; + y = round(linspace(Limit{3}(1),Limit{3}(2),Rows + 1) * (Monitor(4) - Taskbar_Height)) + Taskbar_Height + 1; + clear Size; + [Size(:,:,1),Size(:,:,2)] = meshgrid(diff(x),diff(y)); + + % ===== Output ==================================================== + AR_Mean_Prev = AR_Mean; + AR_Mean = mean(mean(Size(:,:,1) ./ Size(:,:,2))); + if (AR_Mean > AR_Ideal) + AR_Error = abs([AR_Ideal - AR_Mean_Prev,AR_Ideal - AR_Mean]); + if (AR_Error(1) < AR_Error(2)) + Rows = i - 1; + end + Cols = ceil((nFig_Dist + Offset) / Rows); + clear Size; + break; + end + end +elseif (Rows == (-1)) + Rows = ceil((nFig_Dist + Offset) / Cols); +elseif (Cols == (-1)) + Cols = ceil((nFig_Dist + Offset) / Rows); +end + +% ========================================================================= +% ===== Location matrix =================================================== +% ========================================================================= + +Sets = ceil(nFig_Dist / (Rows * Cols) + Offset); +Mat = nan(Rows,Cols,Sets); +if (Transpose) + Mat = permute(Mat,[2,1,3]); +end +if (isempty(Order)) + Order = (1:sum(Fig_Dist)); +end +Temp = sort(Fig_Number(Fig_Dist)); +if (max(Order) > numel(Temp)) + error('The ordering command is related to the input - not the actual figure numbers! Returning...'); +end +Mat((1:nFig_Dist) + Offset) = Temp(Order); +if (Transpose) + Mat = permute(Mat,[2,1,3]); +end +if (strcmp(Extra,'ignore')) + Sets = 1; +end + +% ========================================================================= +% ===== Position and size ================================================= +% ========================================================================= + +% ===== Grid ============================================================== +x = round(linspace(Limit{2}(1),Limit{2}(2),Cols + 1) * Monitor(3)) + 1; +y = round(linspace(Limit{3}(1),Limit{3}(2),Rows + 1) * (Monitor(4) - Taskbar_Height)) + Taskbar_Height + 1; + +% ===== Scale ============================================================= +if (isempty(Scale_Orig)) + Scale_Orig = [x(1),y(end)]; +end +if ((all(mod(Scale_Orig,1) == 0)) && (any(Scale_Orig > 1))) + ScaleOrig_Pixel = Scale_Orig; +else + ScaleOrig_Pixel = Monitor(3:4) .* Scale_Orig; +end +if (numel(Scale) == 1) + Scale(2) = Scale(1); +end +x = (x - ScaleOrig_Pixel(1)) * Scale(1) + ScaleOrig_Pixel(1); +y = (y - ScaleOrig_Pixel(2)) * Scale(2) + ScaleOrig_Pixel(2); + +% ===== Positon =========================================================== +[FPos(:,:,1),FPos(:,:,2)] = meshgrid(x(1:end-1),y(1:end-1)); +FPos(:,:,2) = flipud(FPos(:,:,2)); +FPos(:,:,1) = FPos(:,:,1) + Monitor(1) - 1; +FPos(:,:,2) = FPos(:,:,2) + Monitor(2) - 1; + +% ===== Size ============================================================== +[Size(:,:,1),Size(:,:,2)] = meshgrid(diff(x),diff(y)); + +% ===== Adjust ============================================================ +if (any(Adjust ~= 0)) + if (all(mod(Adjust,1) == 0)) + Adjust_Pixels = Adjust; + else + Adjust_Pixels = round(Adjust .* (Monitor(3:4) + [0,-Taskbar_Height])); + end +else + Adjust_Pixels = [0,0]; +end + +% ========================================================================= +% ===== Distribute figures ================================================ +% ========================================================================= + +for s = 1:Sets + for i = 1:size(Mat,1) + for j = 1:size(Mat,2) + if (~isnan(Mat(i,j,s))) + % ===== Position and figure =============================== + Pos_Temp = [squeeze(FPos(i,j,:))' + Adjust_Pixels,squeeze(Size(i,j,:))']; + gcf_Temp = Fig_Object(Fig_Number == Mat(i,j,s)); + gca_Temp = get(gcf_Temp,'CurrentAxes'); + + % ===== Freeze size ======================================= + if (FreezeSize) + Pos_Orig = get(gcf_Temp,'Position'); + Pos_Temp(2) = Pos_Temp(2) + Pos_Temp(4) - Pos_Orig(4); + Pos_Temp(3:4) = Pos_Orig(3:4); + end + + % ===== Focus figures to bring to front =================== + figure(gcf_Temp); + + % ===== Set units ========================================= + if (~isempty(Menu)) + set(gcf_Temp,'MenuBar',Menu); + end + if (Mat(i,j,s) < 0) + drawnow; + end + gca_Units_Prev = get(gca_Temp,'Units'); + gcf_Units_Prev = get(gcf_Temp,'Units'); + + % ===== Distribute figure ================================= + set(gca_Temp,'Units','normalized'); + set(gcf_Temp,'Units','pixels','OuterPosition',Pos_Temp); + set(gcf_Temp,'Units',gcf_Units_Prev); + + % ===== Apply tight ======================================= + if ((Tight) && (Mat(i,j,s) > 0)) + drawnow; + set(gca_Temp,'Position',[get(gca_Temp,'TightInset') * eye(4,2),1 - get(gca_Temp,'TightInset') * [1,0,1,0;0,1,0,1]']); + end + set(gca_Temp,'Units',gca_Units_Prev); + end + end + end +end + +% ========================================================================= +% ===== Check for new updates ============================================= +% ========================================================================= + +% This feature check for a new version of distFig. It is only an attempt, +% so it might not work without bugs. It can be disables by setting the +% variable below called "Update" to "false" or by deleting this whole +% section - this won't affect the rest of the function. +% +% It generates a .txt file called "distFig_Update.txt" located in the same +% folder as distFig.m, which holds the date for the last time the function +% checked for updates. In order to not check for updates all the time, the +% function only does this ONCE every 7 days (variable "Check_Interval"), +% and at max once for every started MATLAB session. Also, it uses appdata, +% so if you're using this as well, it might display messages multiple times +% within a session, if an update is available, if appdata is deleted. +% +% The update feature works by scanning the file exchange page for distFig +% for a string value called "datePublished", and compares it to the date of +% the current version (variable "Date_Current"). If these are not the same, +% a hyperlink will be shown to the function page on file exchange page. It +% thus depends on a very specific format, which might differ(?) from +% different languages - I'm not aware whether this is true, so please +% contact me on AndersSSimonsen@GMail.com if you find this to be true, so I +% can fix the feature. :) + +% ===== DISABLE THE UPDATE FEATURE BY SETTING THIS VALUE TO false ========= +Update = true; +% ===== DISABLE THE UPDATE FEATURE BY SETTING THIS VALUE TO false ========= + +if (Update) + try + % ===== Initialize ================================================ + Date_Current = [2015,03,31]; + Check_Interval = 7; + Check = false; + + % ===== Path of update file ======================================= + Path = mfilename('fullpath'); + Path = sprintf('%s\\distFig_Update.txt',Path(1:end-numel('\distFig'))); + + if (isempty(getappdata(0,'distFig_Update'))) + % ===== Set appdata =========================================== + setappdata(0,'distFig_Update',1); + + % ===== Read update file ====================================== + File_ID = fopen(Path,'r'); + Clock = clock; + Date_Today = Clock(1:3); + if (File_ID == (-1)) + % ===== Generate update file ============================== + File_ID = fopen(Path,'w'); + fprintf(File_ID,'%d %d %d',Date_Today(1),Date_Today(2),Date_Today(3)); + fclose(File_ID); + Check = true; + else + % ===== Read last date ==================================== + Data = textscan(File_ID,'%s','delimiter',''); + if (strcmp(Data{1},'DISABLE')) + Check = false; + else + Date_Last_Checked = cell2mat(textscan(Data{1}{1},'%f %f %f')); + + % ===== Write new date ================================ + File_ID = fopen(Path,'w'); + fprintf(File_ID,'%d %d %d',Date_Today(1),Date_Today(2),Date_Today(3)); + fclose(File_ID); + + % ===== Check for new updates? ======================== + Days_Elapsed = etime([Date_Today,zeros(1,3)],[Date_Last_Checked,zeros(1,3)]) / (60^2 * 24); + if (Days_Elapsed > Check_Interval) + Check = true; + end + end + end + + % ===== Check for updates ===================================== + if (Check) + % ===== Read File Exchange date =========================== + Data = urlread('http://se.mathworks.com/matlabcentral/fileexchange/37176-distribute-figures'); + Temp = Data((-1:100) + regexp(Data,'datePublished')); + Date_Online = cell2mat(textscan(Temp(26:end),'%f-%f-%f')); + + % ===== New update available? ============================= + if (~all(Date_Current == Date_Online)) + setappdata(0,'distFig_Update',2); + setappdata(0,'distFig_Online_Date',Date_Online); + end + end + end + + % ===== Message =================================================== + if (getappdata(0,'distFig_Update') == 2) + try + % ===== New version ======================================= + Date_Online = getappdata(0,'distFig_Online_Date'); + fprintf('New update available for distFig! '); + disp('Download here') + fprintf('\tCurrent version date:\t%02.0f-%02.0f-%02.0f\n',Date_Current(1),Date_Current(2),Date_Current(3)); + fprintf('\tOnline version date:\t%02.0f-%02.0f-%02.0f\n',Date_Online(1),Date_Online(2),Date_Online(3)); + + % ===== Postpone ========================================== + fprintf('Click here to postpone this message for %d days: ',Check_Interval); + Command = sprintf([... + 'setappdata(0,''distFig_Update'',1);',... + 'fprintf(''distFig update message postponed for %d days!\\n'');' + ],Check_Interval); + disp(sprintf('Postpone update message',Command)); %#ok + + % ===== Disable =========================================== + fprintf('Click here to disable the update feature forever: '); + Command = sprintf([... + 'File_ID = fopen(''%s'',''w'');',... + 'fprintf(File_ID,''DISABLE'');',... + 'fclose(File_ID);',... + 'setappdata(0,''distFig_Update'',1);',... + 'fprintf(''distFig update feature disabled!\\n'');' + ],Path); + disp(sprintf('Disable update feature',Command)); %#ok + catch + setappdata(0,'distFig_Update',1); + end + end + catch Error %#ok + % ===== Error handling ============================================ + try + Path_Error = [Path(1:end-numel('\distFig_Update.txt')),'\distFig_Error.mat']; + fprintf([ + 'There was an error in distFig when checking for updates.',... + '\nPlease report this to AndersSSimonsen@GMail.com by sending the error-file "distFig_Error.mat" located in %s. :)\n\n'],Path_Error); + AppData = getappdata(0); %#ok + save(Path_Error); + catch + end + end +end \ No newline at end of file diff --git a/uvhAssembly.m b/uvhAssembly.m index 662d60d3..a49554fa 100755 --- a/uvhAssembly.m +++ b/uvhAssembly.m @@ -190,27 +190,59 @@ Kxu0=Kxu ; Kxv0=Kxv ; Kyu0=Kyu ; Kyv0=Kyv ; Kxh0=Kxh ; Kyh0=Kyh ; Khu0=Khu ; Khv0=Khv ; Khh0=Khh; - -for Iint=1:MUA.nip - - - [Tx1,Fx1,Ty1,Fy1,Th1,Fh1,Kxu1,Kxv1,Kyu1,Kyv1,Kxh1,Kyh1,Khu1,Khv1,Khh1]=... - uvhAssemblyIntPointImplicitSUPG(Iint,ndim,MUA,... - bnod,hnod,unod,vnod,AGlennod,nnod,Cnod,mnod,h0nod,u0nod,v0nod,as0nod,ab0nod,as1nod,ab1nod,dadhnod,Bnod,Snod,rhonod,... - uonod,vonod,Conod,monod,uanod,vanod,Canod,manod,... - CtrlVar,rhow,g,Ronly,ca,sa,dt,... - Tx0,Fx0,Ty0,Fy0,Th0,Fh0,Kxu0,Kxv0,Kyu0,Kyv0,Kxh0,Kyh0,Khu0,Khv0,Khh0); +if CtrlVar.Parallel.uvhAssembly.parfor + parfor Iint=1:MUA.nip + + + [Tx1,Fx1,Ty1,Fy1,Th1,Fh1,Kxu1,Kxv1,Kyu1,Kyv1,Kxh1,Kyh1,Khu1,Khv1,Khh1]=... + uvhAssemblyIntPointImplicitSUPG(Iint,ndim,MUA,... + bnod,hnod,unod,vnod,AGlennod,nnod,Cnod,mnod,h0nod,u0nod,v0nod,as0nod,ab0nod,as1nod,ab1nod,dadhnod,Bnod,Snod,rhonod,... + uonod,vonod,Conod,monod,uanod,vanod,Canod,manod,... + CtrlVar,rhow,g,Ronly,ca,sa,dt,... + Tx0,Fx0,Ty0,Fy0,Th0,Fh0,Kxu0,Kxv0,Kyu0,Kyv0,Kxh0,Kyh0,Khu0,Khv0,Khh0); + + Tx=Tx+Tx1; Fx=Fx+Fx1; + Ty=Ty+Ty1; Fy=Fy+Fy1; + Th=Th+Th1; Fh=Fh+Fh1; + + Kxu=Kxu+Kxu1; Kxv=Kxv+Kxv1; + Kyu=Kyu+Kyu1; Kyv=Kyv+Kyv1; + Kxh=Kxh+Kxh1; Kyh=Kyh+Kyh1; + Khu=Khu+Khu1; Khv=Khv+Khv1; Khh=Khh+Khh1; + + end - Tx=Tx+Tx1; Fx=Fx+Fx1; - Ty=Ty+Ty1; Fy=Fy+Fy1; - Th=Th+Th1; Fh=Fh+Fh1; +else - Kxu=Kxu+Kxu1; Kxv=Kxv+Kxv1; - Kyu=Kyu+Kyu1; Kyv=Kyv+Kyv1; - Kxh=Kxh+Kxh1; Kyh=Kyh+Kyh1; - Khu=Khu+Khu1; Khv=Khv+Khv1; Khh=Khh+Khh1; + for Iint=1:MUA.nip + + [Tx1,Fx1,Ty1,Fy1,Th1,Fh1,Kxu1,Kxv1,Kyu1,Kyv1,Kxh1,Kyh1,Khu1,Khv1,Khh1]=... + uvhAssemblyIntPointImplicitSUPG(Iint,ndim,MUA,... + bnod,hnod,unod,vnod,AGlennod,nnod,Cnod,mnod,h0nod,u0nod,v0nod,as0nod,ab0nod,as1nod,ab1nod,dadhnod,Bnod,Snod,rhonod,... + uonod,vonod,Conod,monod,uanod,vanod,Canod,manod,... + CtrlVar,rhow,g,Ronly,ca,sa,dt,... + Tx0,Fx0,Ty0,Fy0,Th0,Fh0,Kxu0,Kxv0,Kyu0,Kyv0,Kxh0,Kyh0,Khu0,Khv0,Khh0); + + Tx=Tx+Tx1; Fx=Fx+Fx1; + Ty=Ty+Ty1; Fy=Fy+Fy1; + Th=Th+Th1; Fh=Fh+Fh1; + + Kxu=Kxu+Kxu1; Kxv=Kxv+Kxv1; + Kyu=Kyu+Kyu1; Kyv=Kyv+Kyv1; + Kxh=Kxh+Kxh1; Kyh=Kyh+Kyh1; + Khu=Khu+Khu1; Khv=Khv+Khv1; Khh=Khh+Khh1; + + end end + + + + + + + + % case 'shocks' % % for Iint=1:MUA.nip diff --git a/uvhAssemblySPMD.m b/uvhAssemblySPMD.m new file mode 100644 index 00000000..bcb7a550 --- /dev/null +++ b/uvhAssemblySPMD.m @@ -0,0 +1,36 @@ +function [UserVar,RunInfo,R,K,Tint,Fext]=uvhAssemblySPMD(UserVar,RunInfo,CtrlVar,MUA,F0,F1,ZeroFields) + + +nW=CtrlVar.NumWorkers; +N=ceil(MUA.Nele/nW) ; + + +i1=1 ; i2=N; +for iWorker=1:nW + + Partition=[i1:i2] ; + i1=i2+1 ; + i2=min([i2+N,MUA.Nele]); + + M{iWorker}=MUA; + M{iWorker}.connectivity=MUA.connectivity(Partition,:); + M{iWorker}.Nele=numel(Partition); + M{iWorker}.Deriv=MUA.Deriv(Partition,:,:,:); + M{iWorker}.DetJ=MUA.DetJ(Partition,:); + +end + +Tint=[] ; Fext=[]; + +spmd + [~,~,rr,kk]=uvhAssembly(UserVar,RunInfo,CtrlVar,M{labindex},F0,F1,ZeroFields); +end + +R=rr{1}; K=kk{1}; +for iWorker=2:nW + R=R+rr{iWorker}; + K=K+kk{iWorker}; +end + + +end \ No newline at end of file