Commit 9fc350c3 authored by Lukas Aspöck's avatar Lukas Aspöck

Merge branch 'master' of https://git.rwth-aachen.de/ita/toolbox

parents 9922a3a1 37cf998b
......@@ -24,5 +24,9 @@ Thumbs.db
svnaccess
*.lib
*.exp
itaRaven.ini
*.daff
*.mph
sh.exe.stackdump
itaRaven.ini
itaComsol.ini
itaReceiver.ini
......@@ -408,6 +408,7 @@ classdef itaHRTF < itaAudio
end
metadata = DAFFv17('getMetadata', handleDaff);
DAFFv17('close', handleDaff);
catch
disp( 'Could not read DAFF file right away, falling back to old version and retrying ...' );
......@@ -448,6 +449,8 @@ classdef itaHRTF < itaAudio
coordDaff(iDir,:) = DAFFv15( 'getRecordCoords', handleDaff, 'data', iDir )';
counter= counter+2;
end
DAFFv15('close', handleDaff);
end
% Proceed (version independent)
......
......@@ -90,11 +90,11 @@ end
if sArgs.createPlot
if strcmpi(sArgs.type,'astm')
refCurve = refCurve + 110 - impactInsulationClass;
plotResult = itaResult([nan(sum(freqVector<min(freq)),1); 10.^((refCurve)./20); nan(sum(freqVector>max(freq)),1)],freqVector,'freq');
else
refCurve = refCurve + impactInsulationClass;
plotResult = itaResult([[nan(sum(freqVector<min(freq)),1); 10.^((refCurve)./20); nan(sum(freqVector>max(freq)),1)], [ones(sum(freqVector<=500),1)*10.^(refCurve(freq == 500)./20); nan(sum(freqVector>500),1)]],freqVector,'freq');
end
plotResult = itaResult([[nan(sum(freqVector<min(freq)),1); 10.^((refCurve)./20); nan(sum(freqVector>max(freq)),1)], [ones(sum(freqVector<=500),1)*10.^(refCurve(freq == 500)./20); nan(sum(freqVector>500),1)]],freqVector,'freq');
fgh = ita_plot_freq(data);
ita_plot_freq(plotResult,'figure_handle',fgh,'axes_handle',gca,'hold');
bar(gca,deficiencies.freqVector,deficiencies.freq,'hist');
......
classdef itaAc3dVisualizer < itaAbstract3DModelVisualizer
%itaAc3dVisualizer This class is used to visualize an itaAc3dModel.
% Parameters for the plot are defined using class properties.
% Adjusting these leads to a real-time update the plot (if
% autoRefresh is set to true).
%
% See also itaAc3dVisualizer, itaAc3dModel
%
% Reference page in Help browser
% <a href="matlab:doc itaAc3dVisualizer">doc itaAc3dVisualizer</a>
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
properties(Hidden = true)
axesMapping = [1 -3 2]; %Maps data from .ac3d file to fit to the plot (default is no transform)
end
%% Constructing / Model related
methods
function obj = itaAc3dVisualizer(input)
%Expects a single input of one of the following options:
%1) A .ac filename, pointing to a valid AC3D file
%2) An AC3D object (see load_ac3d)
obj.SetModel(input);
end
function SetModel(obj, input)
%Model can be set using either:
%1) An .ac filename, pointing to a valid AC3D file
%2) An AC3D object (see load_ac3d)
if ischar(input) && isrow(input)
if ~contains(input, '.ac')
error('Given filename does not point to an AC3D file')
end
obj.mModel = load_ac3d(input);
elseif isa(input, 'load_ac3d') && isscalar(input)
obj.mModel = input;
else
error('Input must be either a valid .ac filename or a AC3D object (load_ac3d).')
end
obj.clearPlotItems();
obj.mBoundaryGroupNames = obj.mModel.getMaterialNames;
obj.mBoundaryGroupVisibility = true( 1, obj.numberOfBoundaryGroups() );
if obj.autoRefresh && obj.axesSpecified()
obj.RefreshPlot();
end
end
end
methods(Access = protected)
function out = numberOfBoundaryGroups(this)
out = numel(this.mModel.bcGroups);
end
end
%% Plot Items
methods(Access = protected)
%-----------Create-------------------------------------------------
function plotBoundaryGroups(this)
invertAxes = sign(this.axesMapping);
swapAxes = abs(this.axesMapping);
boundaryGroups = this.mModel.bcGroups;
modelNodes = this.mModel.nodes;
this.mBoundaryPlotHandles = cell(1, numel(boundaryGroups));
for groupID = 1:numel(boundaryGroups)
groupPolygons = boundaryGroups{groupID}.polygons;
this.mBoundaryPlotHandles{groupID} = gobjects(size(groupPolygons));
for polyID = 1:length(groupPolygons)
this.mBoundaryPlotHandles{groupID}(polyID) = patch(this.mAxes,...
modelNodes(groupPolygons{polyID}(:,1),swapAxes(1)) * invertAxes(1), ...
modelNodes(groupPolygons{polyID}(:,1),swapAxes(2)) * invertAxes(2), ...
modelNodes(groupPolygons{polyID}(:,1),swapAxes(3)) * invertAxes(3), ...
boundaryGroups{groupID}.color, 'LineStyle', 'none');
end
end
end
function plotEdges(this)
invertAxes = sign(this.axesMapping);
swapAxes = abs(this.axesMapping);
polygons = this.mModel.polygons;
modelNodes = this.mModel.nodes;
this.mEdgePlotHandles = gobjects(size(polygons));
for polyID = 1:numel(polygons)
polyNodes = polygons{polyID}(:,1);
this.mEdgePlotHandles(polyID) = line(this.mAxes,...
modelNodes([polyNodes; polyNodes(1)],swapAxes(1)) * invertAxes(1), ...
modelNodes([polyNodes; polyNodes(1)],swapAxes(2)) * invertAxes(2), ...
modelNodes([polyNodes; polyNodes(1)],swapAxes(3)) * invertAxes(3));
end
end
end
%% Applying Plot Settings
methods(Access = protected)
function applyAllSettings(this)
applyAllSettings@itaAbstract3DModelVisualizer(this);
end
end
end
classdef itaComsolImpedance < handle
%itaComsolImpedance Represents an impedance boundary condition in an
%itaComsolModel
% Provides static create functions that generate an itaComsolImpedance
% for a given itaComsolModel using a boundary group name and an
% itaMaterial or itaSuper.Therefore. suitable physics and interpolation
% nodes are created and linked apropriately. All comsol nodes
% representing this impedance are stored for later modification.
%
% See also itaComsolModel, itaComsolServer, itaComsolSource,
% itaComsolReceiver
%
% Reference page in Help browser
% <a href="matlab:doc itaComsolImpedance">doc itaComsolImpedance</a>
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
properties(Access = private)
mModel;
mImpedancePhysicsNode;
mImpedanceRealDataNode;
mImpedanceImagDataNode;
end
%% Constructor
methods
function obj = itaComsolImpedance(comsolModel, impedancePhysicsNode, realInterpolationNode, imagInterpolationNode)
%Constuctor should not be used manually. Use static Create
%functions instead!
assert(isa(comsolModel, 'itaComsolModel'), 'First input must be a single itaComsolModel')
assert(isa(impedancePhysicsNode, 'com.comsol.clientapi.physics.impl.PhysicsFeatureClient'), 'Second input must be a comsol physics feature node')
if nargin > 2
assert(isa(realInterpolationNode, 'com.comsol.clientapi.impl.FunctionFeatureClient'), 'Third input must be a comsol function feature node')
assert(isa(imagInterpolationNode, 'com.comsol.clientapi.impl.FunctionFeatureClient'), 'Fourth input must be a comsol function feature node')
else
realInterpolationNode = [];
imagInterpolationNode = [];
end
obj.mModel = comsolModel;
obj.mImpedancePhysicsNode = impedancePhysicsNode;
obj.mImpedanceRealDataNode = realInterpolationNode;
obj.mImpedanceImagDataNode = imagInterpolationNode;
end
end
%----------Static Creators------------
methods(Static = true)
function obj = Create(comsolModel, boundaryGroupName, data)
%Creates an impedance boundary condition for the given comsol
%model using either an itaResult or itaMaterial. The impedance
%is applied to the boundary group (2D Comsol selection) with
%the specified name.
% Inputs:
% comsolModel Comsol model, the impedance is created for [itaComsolModel]
% boundaryGroupName Name of the boundary group the impedance is created for [char row vector]
% data Object with impedance data [itaResult / itaMaterial]
assert(isa(comsolModel, 'itaComsolModel'), 'First input must be a single itaComsolModel')
assert(ischar(boundaryGroupName) && isrow(boundaryGroupName), 'Second input must be a char row vector')
assert(isvarname(strrep(boundaryGroupName, ' ', '_')), 'Given boundary group name must be valid variable name (whitespace allowed)')
dataAssertStr = 'Third input must either be an itaMaterial with a valid impedance or a single itaSuper';
assert(isa(data, 'itaMaterial') || isa(data, 'itaSuper'), dataAssertStr)
if isa(data, 'itaSuper')
assert(numel(data) == 1 && data.nChannels == 1, dataAssertStr)
material = itaMaterial;
material.impedance = data;
else
material = data;
end
assert(material.HasImpedance(), dataAssertStr)
boundaryGroupNode = comsolModel.selection.BoundaryGroup(boundaryGroupName);
assert(~isempty(boundaryGroupNode), 'No boundary group with given name found!')
baseTag = strrep(boundaryGroupName, ' ', '_');
interpolationBaseTag = [baseTag '_impedance'];
impedanceTag = [baseTag '_impedance'];
selectionTag = char(boundaryGroupNode.tag);
switch material.impedanceType
case ImpedanceType.SoundHard
obj = itaComsolImpedance.createSoundHard(comsolModel, impedanceTag, selectionTag);
case ImpedanceType.UserDefined
obj = itaComsolImpedance.createUserDefinedImpedance(...
comsolModel, material, interpolationBaseTag, impedanceTag, selectionTag);
otherwise
error('Unsupported ImpedanceType')
end
obj.Enable;
end
end
methods(Static = true, Access = private)
function obj = createSoundHard(comsolModel, impedanceTag, selectionTag)
impedanceNode = comsolModel.physics.CreateImpedance(impedanceTag, selectionTag, 'inf');
obj = itaComsolImpedance(comsolModel, impedanceNode);
end
function obj = createUserDefinedImpedance(comsolModel, material, interpolationBaseTag, impedanceTag, selectionTag)
[realInterpolationNode, imagInterpolationNode, funcExpression] = ...
itaComsolImpedance.createImpedanceInterpolation(comsolModel, interpolationBaseTag, material.impedance.freqVector, material.impedance.freqData);
impedanceNode = comsolModel.physics.CreateImpedance(impedanceTag, selectionTag, funcExpression);
obj = itaComsolImpedance(comsolModel, impedanceNode, realInterpolationNode, imagInterpolationNode);
end
end
%% Enable / Disable
methods
function Disable(obj)
obj.setActive(false);
end
function Enable(obj)
obj.setActive(true);
end
end
methods(Access = private)
function setActive(obj, bool)
if ~isempty(obj.mImpedancePhysicsNode)
obj.mImpedancePhysicsNode.active(bool);
end
if ~isempty(obj.mImpedanceRealDataNode)
obj.mImpedanceRealDataNode.active(bool);
end
if ~isempty(obj.mImpedanceImagDataNode)
obj.mImpedanceImagDataNode.active(bool);
end
end
end
%% Helpers
methods(Access = private, Static = true)
function [realInterpolationNode, imagInterpolationNode, funcExpression] = createImpedanceInterpolation(comsolModel, interpolationBaseTag, freqVector, complexDataVector)
[realInterpolationNode, imagInterpolationNode, funcExpression] = comsolModel.func.CreateComplexInterpolation(interpolationBaseTag, freqVector, complexDataVector, 'Pa / m * s');
end
end
end
\ No newline at end of file
classdef itaComsolModel < handle
%itaComsolModel Interface to adjust and work with Comsol models
% This class represents a model tree similar to the one within
% Comsol. Each child node of a model is represented by a particular
% class (e.g. the physics node is represented by itaComsolPhysics).
% Through these sub-classes it provides interfaces to adjust certain
% parameters or access data. An overview is given below. More details
% can be found in the documentation of the respective classes.
%
% Note, that it is crucial to define the basis of the comsol model in
% Comsol itself. This includes:
% -Geometry
% -Materials
% -Physics
% -especially, impedances at boundaries
% -sources
% -Mesh
% -Study
%
% Using an itaComsolModel and its related classes, it is possible to create/adjust:
% -Global Definitions
% -Interpolations
% -Geometry
% -for sources (points / boundary surfaces)
% -Materials
% -...(to be added in future)
% -Physics
% -frequency dependent values for boundary impedances
% -frequency dependent source parameters (velocity / pressure)
% -Mesh
% -mesh size
% -Result
% -retrieve results in ita-formats
% -Study
% -frequency vector
% -run simulation
% -Batch
% -create batch commands to run simulation
%
% See also itaComsolServer, itaComsolBatch, itaComsolExport,
% itaComsolFunction, itaComsolGeometry, itaComsolMaterial,
% itaComsolMesh, itaComsolParameters, itaComsolPhysics,
% itaComsolResult, itaComsolSelection, itaComsolStudy
%
% Reference page in Help browser
% <a href="matlab:doc itaComsolModel">doc itaComsolModel</a>
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
properties(Access = private)
mModel; %Comsol model node (com.comsol.clientapi.impl.ModelClient)
mParameterNode;
mSelectionNode;
mFunctionNode;
mGeometryNode;
mMaterialNode;
mPhysicsNode;
mMeshNode;
mStudyNode;
mBatchNode;
mResultNode;
end
properties(Dependent = true, SetAccess = private)
modelNode; %The comsol model node
parameter; %Interface to access Comsol parameter clients (itaComsolParameters)
selection; %Interface to access Comsol selection clients (itaComsolSelection)
func; %Interface to access Comsol function clients (itaComsolFunction)
geometry; %Interface to access Comsol geometry sequences (itaComsolMaterial)
material; %Interface to access Comsol material clients (itaComsolGeometry)
physics; %Interface to access Comsol physics sequences (itaComsolPhysics)
mesh; %Interface to access Comsol mesh sequences (itaComsolMesh)
study; %Interface to access Comsol study clients (itaComsolStudy)
batch; %Interface to access Comsol batch clients (itaComsolBatch)
result; %Interface to evaluate results (itaComsolResult)
end
methods
function out = get.modelNode(obj)
out = obj.mModel;
end
function out = get.parameter(obj)
out = obj.mParameterNode;
end
function out = get.selection(obj)
out = obj.mSelectionNode;
end
function out = get.func(obj)
out = obj.mFunctionNode;
end
function out = get.geometry(obj)
out = obj.mGeometryNode;
end
function out = get.material(obj)
out = obj.mMaterialNode;
end
function out = get.physics(obj)
out = obj.mPhysicsNode;
end
function out = get.mesh(obj)
out = obj.mMeshNode;
end
function out = get.study(obj)
out = obj.mStudyNode;
end
function out = get.batch(obj)
out = obj.mBatchNode;
end
function out = get.result(obj)
out = obj.mResultNode;
end
end
%% Constructor
methods
function obj = itaComsolModel(comsolModel)
if ~isa(comsolModel, 'com.comsol.clientapi.impl.ModelClient')
error('Input must be a comsol model (com.comsol.clientapi.impl.ModelClient)')
end
obj.mModel = comsolModel;
obj.mParameterNode = itaComsolParameters(obj);
obj.mSelectionNode = itaComsolSelection(obj);
obj.mFunctionNode = itaComsolFunction(obj);
obj.mGeometryNode = itaComsolGeometry(obj);
obj.mMaterialNode = itaComsolMaterial(obj);
obj.mPhysicsNode = itaComsolPhysics(obj);
obj.mMeshNode = itaComsolMesh(obj);
obj.mStudyNode = itaComsolStudy(obj);
obj.mBatchNode = itaComsolBatch(obj);
obj.mResultNode = itaComsolResult(obj);
assert(~isempty(obj.mGeometryNode.activeNode), 'No Comsol geometry node found')
assert(~isempty(obj.mPhysicsNode.activeNode), 'No Comsol physics node found')
assert(~isempty(obj.mMeshNode.activeNode), 'No Comsol mesh node found')
assert(~isempty(obj.mStudyNode.activeNode), 'No Comsol study node found')
end
end
end
classdef itaComsolReceiver < handle
%itaComsolReceiver Represents an itaReceiver in an itaComsolModel
% Provides static create functions that generate an itaComsolReceiver
% for a given itaComsolModel using an itaReceiver. Therefore depending
% on the receiver type, suitable geometry nodes are created. All comsol
% nodes representing this receiver are stored for later modification.
%
% See also itaComsolModel, itaComsolServer, itaComsolSource,
% itaComsolImpedance
%
% Reference page in Help browser
% <a href="matlab:doc itaComsolReceiver">doc itaComsolReceiver</a>
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
properties(Access = private)
mModel;
mGeometryNodes;
mSelectionTags = {};
mMeshNodes;
mActive = true;
end
properties(Dependent = true, SetAccess = private)
selectionTags; %Includes tags to the geometry nodes representing this receiver
end
properties(Constant = true)
dummyHeadGeometryTagSuffix = '_dummyHeadGeometry';
dummyHeadMeshTagSuffix = '_dummyHeadMeshSize';
geometryTagSuffixes = {itaComsolReceiver.dummyHeadGeometryTagSuffix};
end
%% Constructor
methods
function obj = itaComsolReceiver(comsolModel, receiverGeometryNode, selectionTags, meshNodes)
%Constructor should only be used to create empty object (no
%input). To create a non-empty object, use static Create functions!
%To create empty object
if nargin == 0; return; end
%Geometry only
assert(isa(comsolModel, 'itaComsolModel'), 'First input must be a single itaComsolModel');
assert(isa(receiverGeometryNode, 'com.comsol.clientapi.impl.GeomFeatureClient') ||...
isa(receiverGeometryNode, 'com.comsol.clientapi.impl.GeomFeatureClient[]'),...
'Second input must be a comsol geometry feature node');
if ischar(selectionTags) && isrow(selectionTags); selectionTags = {selectionTags}; end
assert(~isempty(selectionTags) && iscellstr(selectionTags),...
'Third input must be a cell of char vectors');
if nargin == 4
assert(isa(meshNodes, 'com.comsol.clientapi.impl.MeshFeatureClient') ||...
isa(meshNodes, 'com.comsol.clientapi.impl.MeshFeatureClient[]'),...
'Fourth input must be a comsol mesh feature node')
else
meshNodes = [];
end
obj.mModel = comsolModel;
obj.mGeometryNodes = receiverGeometryNode;
obj.mSelectionTags = selectionTags;
obj.mMeshNodes = meshNodes;
end
end
%----------Static Creators------------
methods(Static = true)
function obj = Create(comsolModel, receiver)
%Creates an acoustic receiver for the given comsol model using
%an itaReceiver. Geometry of the receiver depends on the
%ReceiverType.
% Inputs:
% comsolModel Comsol model, the receiver is created for [itaComsolModel]
% receiver Object with receiver data [single itaReceiver]
%
% Supported receiver types: Monaural, ITADummyHead
assert(isa(comsolModel, 'itaComsolModel') && isscalar(comsolModel), 'First input must be a single itaComsolModel')
itaComsolReceiver.checkInputForValidItaReceiver(receiver);
switch receiver.type
case ReceiverType.Monaural
obj = itaComsolReceiver();
case ReceiverType.ITADummyHead
obj = itaComsolReceiver.CreateDummyHead(comsolModel, receiver);
otherwise
error('Unknown receiver type. No receiver was created')
end
end
function obj = CreateDummyHead(comsolModel, receiver)
%Creates a dummy head geometry given an itaSource for the given
%comsol model
% In Comsol internally, ...
%
% Inputs:
% comsolModel Comsol model, the receiver is created for [itaComsolModel]
% receiver Object with receiver data [single itaReceiver]
assert(isa(comsolModel, 'itaComsolModel') && isscalar(comsolModel), 'First input must be a single itaComsolModel')
itaComsolReceiver.checkInputForValidItaReceiver(receiver);
assert(receiver.type == ReceiverType.ITADummyHead, 'ReceiverType of given source must be DummyHead')
baseTag = strrep(receiver.name, ' ', '_');
receiverGeometryBaseTag = [baseTag itaComsolReceiver.dummyHeadGeometryTagSuffix];
meshSizeTag = [baseTag itaComsolReceiver.dummyHeadMeshTagSuffix];
geometry = comsolModel.geometry;
[dummyHeadGeometryNodes, selectionTag] = geometry.ImportReceiverGeometry(receiverGeometryBaseTag, receiver);
meshNode = comsolModel.mesh;
sizeNode = meshNode.CreateSize(meshSizeTag, selectionTag);
meshNode.SetPositionOfFeature(meshSizeTag, 1);
meshNode.SetMinimumSizeProperties(sizeNode, ...
'hmax', 0.04, 'hmin', 0.004, 'hgrad', 1.3, 'hcurve', 0.2, 'hnarrow', 1)
obj = itaComsolReceiver(comsolModel, dummyHeadGeometryNodes, selectionTag, sizeNode);
obj.Enable();
end
end
%% Get
methods
function out = get.selectionTags(this)
out = this.mSelectionTags;
end
end
%% Enable / Disable
methods
function Disable(obj)
obj.setActive(false);
end
function Enable(obj)
obj.setActive(true);
end
function out = IsActive(obj)
out = obj.mActive;
end
end
methods(Access = private)
function setActive(obj, bool)
for idxGeom=1:numel(obj.mGeometryNodes)
obj.mGeometryNodes(idxGeom).active(bool);
end
for idxNode=1:numel(obj.mMeshNodes)
obj.mMeshNodes(idxNode).active(bool);
end
obj.mActive = bool;
end
end
%% Helpers
methods(Access = private, Static = true)
function checkInputForValidItaReceiver(receiver)
assert(isa(receiver, 'itaReceiver') && isscalar(receiver),'Input must be a single itaReceiver object')
assert(isvarname( strrep(receiver.name, ' ', '_') ),...
'Name of given receiver must be valid variable name (whitespace allowed)')
assert(receiver.HasSpatialInformation(), 'Geometric information not fully specified for itaReceiver')
end
end
end
\ No newline at end of file
classdef itaComsolServer < handle
%itaComsolServer Interface to start/stop and connect/disconnect
%Comsol Server via Matlab LiveLink
% Also allows to remove comsol models from the server.
%
% Information on the server and LiveLink path are stored in an ini-file.
% This file is created the first time a connection is established.
%
% See also itaComsolModel
%
% Reference page in Help browser
% <a href="matlab:doc itaComsolServer">doc itaComsolServer</a>
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
properties(Access = private)
iniFile;
comsolIni = IniConfig();
comsolServerExePath;
matlabLiveLinkPath;
isConnected = false;
end
properties(Constant = true, Access = private)
iniSectionGlobal = 'Global';
iniTagComsolServer = 'ComsolServerExe';
iniTagMatlabLiveLink = 'MatlabLiveLinkPath';
comsolServerExe = 'comsolmphserver.exe';
end
%% Constructor
methods(Access = private)
function obj = itaComsolServer()