Edit an Abaqus input file and Run it from Matlab - matlab

I need perform 50 Abaqus simulations, each simulation analyses a certain material property and each differs by changing one parameter. So the idea is to write a Matlab script that:
opens the .inp file
edits the material parameter of interest
prints it into a new file which will be the new .inp file
runs it to perform the simulation
This is what I accomplished so far in a very simplified version:
f= fopen('PRD8_30s.inp');
c = textscan(f,'%s %s %s %s %s ','delimiter',',');
fclose(f) ;
S = [c{1}];
A = {'5e-08'} ;
S(12496) = A ;
fid = fopen('file.inp','w') ;
fprintf(fid,'%s \n',S{:} );
fclose(fid) ;
PRD_8_30s.inp
I manually found out the position of the parameter of interest (A at 12496 hence below the line *Viscoelastic). The code actually changes the parameter I need but there are major problems: it prints a new file with additional lines with respect to the original .inp (12552 vs 8737) and it doesn't print the entire .inp but only the first column.
How can I edit the .inp changing the parameter and obtaining a new .inp with the edited parameter that can be used to run the new simulation?
Thank you in advance for your help!

If your input file is not multiple Gb in size, The following might help.
create a template input and mark the parameter you want to change as, for example para_xxxx
Use the following script:
text=fileread('template.inp');
newtext=replace(text,'para_xxxx',newParameter);
fid=fopen('newcase.inp','w');
fprintf(fid,newtext);
fclose(fid);
The file name 'newcase.inp' should be updated each time in the loop.

Related

Kill Excel process created in Matlab

Given that I write to a workbook, I currently kill all Excel processes so that my code works when I call it in a loop.
xlswrite(path,values);
system('taskkill /F /IM EXCEL.EXE');
This makes me unable to run the code while I am working in another Excel file. How do I make it so that Matlab terminates only the Excel processes that itself created?
This was a "feature" introduced somewhere around R2015b to speed up multiple writes to Excel... not very user/memory friendly!
The xlswrite documentation links to this MathWorks Support Answer to manually write to Excel using actxserver, you can then manually delete the COM object referencing Excel.
You can actually edit xlswrite and see that it uses matlab.io.internal.getExcelInstance, which does the same thing and creates a COM interface with actxserver.
A cheeky option would be to copy xlswrite, add the Excel variable it creates as an output, and Quit and delete it afterwards, as shown below. I don't advocate breaking any of The MathWorks' copyright ownership of that function.
A less cheeky option would be to create a comparable function based on the answer I linked above, for writing data only it would look something like this:
function xlswriteClean( File, Data, Range )
% XLSWRITECELAN writes data like XLSWRITE, but deletes the Excel instance!
% XLSWRITECELAN (FILE,DATA,RANGE) writes the variable in
% DATA to FILE, in the range specified by RANGE.
% RANGE is optional, defaults to "A1"
% Obtain the full path name of the file
% Could handle this more elegantly, i.e.
% this always assumes the current directory, but user might give a full path
file = fullfile(pwd, File);
% Open an ActiveX connection to Excel
h = actxserver('excel.application');
%Create a new work book (excel file)
wb = h.WorkBooks.Add();
% Select the appropriate range
if nargin < 3
Range = 'A1';
end
rng = h.Activesheet.get('Range', Range);
% Write the data to the range
rng.value = Data;
% Save the file with the given file name, close Excel
wb.SaveAs( File );
% Clean up - the point of this function
wb.Close;
h.Quit;
h.delete;
end
You can customise basically everything within the new Excel workbook using the COM object h, so you could add any functionality which you use in xlswrite like sheet naming etc.
You can start the excel process by powershell and get its process id then use the process id to kill the process:
[~, pid] = system('powershell (Start-Process excel.exe -passthru).Id');
% Do your work
% ...
system(['powershell Stop-Process -Id ' pid])

Abaqus *.inp file created using Matlab

I was trying to do parametric studies in ABAQUS. I created an *.inp file (master) using GUI in abaqus, then wrote a matlab code to create a new *.inp file using the master. Master *.inp file can be found here and will be required to run the code.
In the new *.inp file everything was same as the master except a few specific lines which I am changing for parametric studies, code is given below. I am getting the files nicely but the problem is ABAQUS can't read the file and gives error messages. By visual inspection I don't find any faults. I guess matlab is writing the *.inp file in some other format which ABAQUS can't interpret.
clc;
%Number of lines to be copied
total_lines=4538; %total number of lines
lines_b4_RP1=4406; % lines before reference point 1
%creating new files
for A=0
for R=[20 30 40 50 100 200 300 400 500]
fileroot = sprintf('P_SHS_120X120X1_NLA_I15_A%dR%d.inp', A,R);
main_inp=fopen('P_SHS_120X120X1_NLA_I15_A0R10.inp','r'); %inputting the main inp file to be copied
wfile=fopen(fileroot,'w+'); %wfile= writing the new file
for i=1:total_lines
data=fgets(main_inp);
if i<lines_b4_RP1
fprintf(wfile,'%s\n', data);
elseif i==lines_b4_RP1
formatline1=('%s\n');
txtline='*Node';
fprintf(wfile, formatline1 ,txtline);
elseif i==(lines_b4_RP1+1)
formatline2=('%d%s%d%s%d%s%d\r\n');
comma=',';
refpt1=1;
xcoord1=R*cosd(A);
ycoord1=R*sind(A);
zcoord1=-20;
fprintf(wfile, formatline2, refpt1,comma,xcoord1,comma,ycoord1,comma,zcoord1);
elseif i==(lines_b4_RP1+2)
fprintf(wfile, formatline1 ,txtline);
elseif i==(lines_b4_RP1+3)
refpt2=2;
xcoord2=R*cosd(A);
ycoord2=R*sind(A);
zcoord2=420;
fprintf(wfile, formatline2 ,refpt2,comma,xcoord2,comma,ycoord2,comma,zcoord2);
elseif i>(lines_b4_RP1+3)
fprintf(wfile,'%s\n', data);
else break;
end
end
fclose(main_inp);
fclose(wfile);
end
end
Thanks in advance.
N.B. A sample *.dat file containing the error message is given here.
You are using fgets to get each line of the input file. From the matlab help:
fgets: Read line from file, keeping newline characters
You then print each line using
fprintf(wfile,'%s\n', data);
This creates two newlines at the end of each data line in the file. A second problem in your file is that you use \r\n in your format specifier. In matlab (unlike C) this will give you two newlines. e.g.
>> fprintf('Hello\rWorld\nFoo\r\nBar\n')
Hello
World
Foo
Bar
>>
I would suggest in future to test this approach with a much simpler format that you can use. Also there is a
*preprint
option that allows you to echo the contents of the input file back into the dat file. This creates big dat files, but it is useful for debugging.

Find and replace text file Matlab

I'm writting a Matlab code that generates an array number and it should replace that each number in a text file (that already exists) and replace all instances with that. The number should be in string format. I've achieved this:
ita='"';
for i=1:size(z,2)
word_to_replace=input('Replace? ','s');
tik=input('Replacement? ','s');
coluna=input('Column? ');
files = dir('*.txt');
for i = 1:numel(files)
if ~files(i).isdir % make sure it is not a directory
contents = fileread(files(i).name);
fh = fopen(files(i).name,'w');
val=num2str(z(i,coluna));
word_replacement=strcat(tik,val,ita);
contents = regexprep(contents,'word_to_replace','word_replacement');
fprintf(fh,contents); % write "replaced" string to file
fclose(fh) % close out file
end
end
end
I want the code to open the file#1 ('file.txt'), find and replace all instances 'word_replacement' with 'word_to_replace' and save to the same file. The number of txt files is undefined, it could be 100 or 10000.
Many thanks in advance.
The problem with your code is the following statement:
contents = regexprep(contents,'word_to_replace','word_replacement');
You are using regular expressions to find any instances of word_to_replace in your text files and changing them to word_replacement. Looking at your code, it seems that these are both variables that contain strings. I'm assuming that you want the contents of the variables instead of the actual name of the variables.
As such, simply remove the quotations around the second and third parameters of regexprep and this should work.
In other words, do this:
contents = regexprep(contents, word_to_replace, word_replacement);

Matlab publish - Want to use a custom file name to publish several pdf files

I have several data log files (here: 34) for those I have to calculate some certain values. I wrote a seperate function to publish the results of the calculation in a pdf file. But I only can publish one file after another, so it takes a while to publish all 34 files.
Now I want to automize that with a loop - importing the data, calculate the values and publish the results for every log file in a new pdf file. I want 34 pdf files for every log file at the end.
My problem is, that I couldn't find a way to rename the pdf files during publishing. The pdf file is always named after the script which is calculating the values. Obviously the pdf is overwritten within a loop. So at the end everything is calculated, but I only have the pdf from the last calculated log file.
There was this hacky solution to change the Matlab publish script, but since I don't have admin rights I can't use that:
"This is really hacky, but I would modify publish to accept a new option prefix. Replace line 93
[scriptDir,prefix] = fileparts(fullPathToScript);
with
if ~isfield(options, 'prefix')
[scriptDir,prefix] = fileparts(fullPathToScript);
else
[scriptDir,~] = fileparts(fullPathToScript);
prefix = options.prefix; end
Now you can set options.prefix to whatever filename you want. If you want to be really hardcore, make the appropriate modifications to supplyDefaultOptions and checkOptionFields as well."
Any suggestions?
Thanks in advance,
Martin
Here's one idea using movefile to rename the resultant published PDF on each iteration:
for i = 1:34
file = publish(files(i)); % Replace with your own command(s)
[pathStr,fileName,ext] = fileparts(file);
newFile = [pathStr filesep() fileName '_' int2str(i) ext]; % Example: append _# to each
[success,msg,msgid] = movefile(file,newFile);
if ~success
error(msgid,msg);
end
end
Also used are fileparts and filesep. See this question for other ways to rename and move files.

MATLAB: How do you insert a line of text at the beginning of a file?

I have a file full of ascii data. How would I append a string to the first line of the file? I cannot find that sort of functionality using fopen (it seems to only append at the end and nothing else.)
The following is a pure MATLAB solution:
% write first line
dlmwrite('output.txt', 'string 1st line', 'delimiter', '')
% append rest of file
dlmwrite('output.txt', fileread('input.txt'), '-append', 'delimiter', '')
% overwrite on original file
movefile('output.txt', 'input.txt')
Option 1:
I would suggest calling some system commands from within MATLAB. One possibility on Windows is to write your new line of text to its own file and then use the DOS for command to concatenate the two files. Here's what the call would look like in MATLAB:
!for %f in ("file1.txt", "file2.txt") do type "%f" >> "new.txt"
I used the ! (bang) operator to invoke the command from within MATLAB. The command above sequentially pipes the contents of "file1.txt" and "file2.txt" to the file "new.txt". Keep in mind that you will probably have to end the first file with a new line character to get things to append correctly.
Another alternative to the above command would be:
!for %f in ("file2.txt") do type "%f" >> "file1.txt"
which appends the contents of "file2.txt" to "file1.txt", resulting in "file1.txt" containing the concatenated text instead of creating a new file.
If you have your file names in strings, you can create the command as a string and use the SYSTEM command instead of the ! operator. For example:
a = 'file1.txt';
b = 'file2.txt';
system(['for %f in ("' b '") do type "%f" >> "' a '"']);
Option 2:
One MATLAB only solution, in addition to Amro's, is:
dlmwrite('file.txt',['first line' 13 10 fileread('file.txt')],'delimiter','');
This uses FILEREAD to read the text file contents into a string, concatenates the new line you want to add (along with the ASCII codes for a carriage return and a line feed/new line), then overwrites the original file using DLMWRITE.
I get the feeling Option #1 might perform faster than this pure MATLAB solution for huge text files, but I don't know that for sure. ;)
How about using the frewind(fid) function to take the pointer to the beginning of the file?
I had a similar requirement and tried frewind() followed by the necessary fprintf() statement.
But, warning: It will overwrite on whichever is the 1st line. Since in my case, I was the one writing the file, I put a dummy data at the starting of the file and then at the end, let that be overwritten after the operations specified above.
BTW, even I am facing one problem with this solution, that, depending on the length(/size) of the dummy data and actual data, the program either leaves part of the dummy data on the same line, or bring my new data to the 2nd line..
Any tip in this regards is highly appreciated.