stress and strain curve with Lammps - lammps

I want to try to draw stress and strain curve for copper nanoparticles with Lammps.
This is my code.
I don't know whether this is correct or not.
Can anybody help me?
It has fix nve for relaxation, but before that has fix nvt ,and these 2 fixes can't come together.
# tensile test
echo both
dimension 3
boundary s p p
units metal
atom_style atomic
##########create box#######
region copperbox block -80 80 -40 40 -40 40 units box
create_box 1 copperbox
lattice fcc 3.61
region copper block -60 60 -20 20 -20 20 units box
create_atoms 1 region copper
mass 1 63.546
thermo_modify lost ignore
region left block -60 -50 -20 20 -20 20 units box
group left region left
region right block 50 60 -20 20 -20 20 units box
group right region right
group middle subtract all left right
timestep 0.002
pair_style eam
pair_coeff * * cu_u3.eam
velocity all create 300 4928459 mom yes rot yes dist uniform
velocity left create 0 4928459 mom yes rot yes dist uniform
velocity right create 0 4928459 mom yes rot yes dist uniform
fix 1 all nvt temp 300 300 0.01
fix 2 left setforce 0 0 0
fix 3 right setforce 0 0 0
fix 4 all nve
thermo 100
run 1000
#####################################
compute 1 middle stress/atom
compute 2 middle reduce sum c_1[1]
dump 1 all custom 100 stress.txt mass x y z c_1[1] c_1[2] c_1[3]
c_1[4] c_1[5] c_1[6]
dump 2 all xyz 100 dump.xyz
#####################################
variable a loop 2
label loopa
fix 8 right move linear 0.2 0 0 units box
fix 9 left move linear 0 0 0 units box
run 1000
#####################################
unfix 8
unfix 9
fix 8 right move linear 0 0 0 units box
fix 9 left move linear 0 0 0 units box
run 40000
#####################################
fix 10 all nve
thermo 100
run 10000
#####################################
variable sigma equal "c_2/(40000)*(10^4)"
variable l2 equal xcm(right,x)
variable l0 equal ${l2}
variable strain equal "(v_l2-v_l0)/(v_l0)*100"
next a
jump in.copper99 loopa
restart 1000 restart.*

Related

How to calculate weighted (grayscale) centroids of pixel clusters contained within bounding boxes on an image

I've written some code in MATLAB that converts an image (of stars) into a grayscale image and then into a binary image using a set threshold and then labels each cluster of pixels (stars) that is above this threshold. The labelling produces an output:
e.g.
[1 1 1 0 0 0 0 0 0
1 1 0 0 0 2 2 2 0
0 0 0 3 3 0 2 0 0
0 0 0 3 3 0 0 0 0]
So each cluster of 1's, 2's, 3's etc. represents a star. After this the code then finds the centroids of each pixel cluster and draws a bounding box around each centroid (centered on the centroid) with an 8 x 8 pixel area. The bounding box limits are made by finding xmax, xmin, ymax, ymin of each calculated centroid, which involves either adding or subtracting 4 (pixels) from the x and y coordinates of each centroid.
The weighted centroid is calculated like so:
x_coordinate_centroid = sum(x_coordinate .* pixel_values) / sum_pixel_values
y_coordinate_centroid = sum(y_coordinate .* pixel_values) / sum_pixel_values
x/y_coordinate and pixel values are for the pixels contained within each bounding box.
The bounding box would surround an 8 x 8 pixel area (with the given intensities) on the grayscale image such as:
[100 100 100 90 20 20 0 0
80 90 100 90 20 30 0 0
50 70 100 70 30 0 20 0
50 0 0 60 30 30 0 0
0 0 0 0 0 0 0 0
0 50 0 0 0 0 0 0
0 40 0 0 0 0 0 0
0 20 0 0 0 0 0 0]
The top left value ([xmin, ymax]), for example, could have image coordinates [41, 14] and an intensity of 100.
The output from my code, for example, could give 5 bounding boxes across the grayscale image. I now need to write code that automatically calculates the weighted centroid of each bounding box region. I'm not sure how to go about this, does anyone have any ideas how this can be achieved?
My code for calculating the centroids and their bounding boxes is shown below.
%% Calculate centroids of each labelled pixel cluster within binary image
N = max(B(:)); % total number of pixel labels generated in output array
sum_total = zeros(N,1); % create N x 1 array of 0's
sum_yv = zeros(N,1); % "
sum_xv = zeros(N,1); % "
for xx=1:size(B,2) % search through y positions
for yy=1:size(B,1) % search through x positions
index = B(yy,xx);
if index>0
sum_total(index) = sum_total(index) + 1;
sum_yv(index) = sum_yv(index) + yy;
sum_xv(index) = sum_xv(index) + xx;
end
end
end
centroids = [sum_xv, sum_yv] ./ sum_total; % calculates centroids for each cluster
x_lower_limits = centroids(:,1)-4;
y_lower_limits = centroids(:,2)+4; % lower on image means larger y coord number
x_upper_limits = centroids(:,1)+4;
y_upper_limits = centroids(:,2)-4; % higher on image means lower y coord number
x_lower_limits(x_lower_limits<1)=1; % limit smallest x coord to image axis (1,y)
y_lower_limits(y_lower_limits>size(binary_image,1))=size(binary_image,1); % limit largest y coord to image axis (x,517)
x_upper_limits(x_upper_limits>size(binary_image,2))=size(binary_image,2); % limit largest x coord to image axis (508,y)
y_upper_limits(y_upper_limits<1)=1; % limit smallest y coord to image axis (x,1)
width = x_upper_limits(:,1) - x_lower_limits(:,1); % width of bounding box
height = y_lower_limits(:,1) - y_upper_limits(:,1); % height of bounding box
hold on
for xl=1:size(x_lower_limits,1)
r(xl)=rectangle('Position',[x_lower_limits(xl,1) y_upper_limits(xl,1) width(xl,1) height(xl,1)],'EdgeColor','r');
end
for i=1:size(centroids,1)
plot(centroids(i,1),centroids(i,2),'rx','MarkerSize',10)
end
hold off
%%

How do I calculate the area of a 3 dimensional projection?

For example, using the following code, I have a coordinate matrix with 3 cubical objects defined by 8 corners each, for a total of 24 coordinates. I apply a rotation to my coordinates, then delete the y coordinate to obtain a projection in the x-z plane. How do I calculate the area of these cubes in the x-z plane, ignoring gaps and accounting for overlap? I have tried using polyarea, but this doesn't seem to work.
clear all
clc
A=[-100 -40 50
-100 -40 0
-120 -40 50
-120 -40 0
-100 5 0
-100 5 50
-120 5 50
-120 5 0
-100 0 52
-100 0 52
20 0 5
20 0 5
-100 50 5
-100 50 5
20 50 52
20 50 52
-30 70 53
-30 70 0
5 70 0
5 70 53
-30 120 53
-30 120 0
5 120 53
5 120 0]; %3 Buildings Coordinate Matrix
theta=60; %Angle
rota = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1]; %Rotation matrix
R=A*rota; %rotates the matrix
R(:,2)=[];%deletes the y column
The first step will be to use convhull (as yar suggests) to get an outline of each projected polygonal region. It should be noted that a convex hull is appropriate to use here since you are dealing with cuboids, which are convex objects. I think you have an error in the coordinates for your second cuboid (located in A(9:16, :)), so I modified your code to the following:
A = [-100 -40 50
-100 -40 0
-120 -40 50
-120 -40 0
-100 5 0
-100 5 50
-120 5 50
-120 5 0
-100 0 52
-100 0 5
20 0 52
20 0 5
-100 50 5
-100 50 52
20 50 5
20 50 52
-30 70 53
-30 70 0
5 70 0
5 70 53
-30 120 53
-30 120 0
5 120 53
5 120 0];
theta = 60;
rota = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1];
R = A*rota;
And you can generate the polygonal outlines and visualize them like so:
nPerPoly = 8;
nPoly = size(R, 1)/nPerPoly;
xPoly = mat2cell(R(:, 1), nPerPoly.*ones(1, nPoly));
zPoly = mat2cell(R(:, 3), nPerPoly.*ones(1, nPoly));
C = cell(1, nPoly);
for iPoly = 1:nPoly
P = convhull(xPoly{iPoly}, zPoly{iPoly});
xPoly{iPoly} = xPoly{iPoly}(P);
zPoly{iPoly} = zPoly{iPoly}(P);
C{iPoly} = P([1:end-1; 2:end].')+nPerPoly.*(iPoly-1); % Constrained edges, needed later
end
figure();
colorOrder = get(gca, 'ColorOrder');
nColors = size(colorOrder, 1);
for iPoly = 1:nPoly
faceColor = colorOrder(rem(iPoly-1, nColors)+1, :);
patch(xPoly{iPoly}, zPoly{iPoly}, faceColor, 'EdgeColor', faceColor, 'FaceAlpha', 0.6);
hold on;
end
axis equal;
axis off;
And here's the plot:
If you wanted to calculate the area of each polygonal projection and add them up it would be very easy: just change the above loop to capture and sum the second output from the calls to convexhull:
totalArea = 0;
for iPoly = 1:nPoly
[~, cuboidArea] = convhull(xPoly{iPoly}, zPoly{iPoly});
totalArea = totalArea+cuboidArea;
end
However, if you want the area of the union of the polygons, you have to account for the overlap. You have a few alternatives. If you have the Mapping Toolbox then you could use the function polybool to get the outline, then use polyarea to compute its area. There are also utilities you can find on the MathWorks File Exchange (such as this and this). I'll show you another alternative here that uses delaunayTriangulation. First we can take the edge constraints C created above to use when creating a triangulation of the projected points:
oldState = warning('off', 'all');
DT = delaunayTriangulation(R(:, [1 3]), vertcat(C{:}));
warning(oldState);
This will automatically create new vertices where the constrained edges intersect. Unfortunately, it will also perform the triangulation on the convex hull of all the points, filling in spots that we don't want filled. Here's what the triangulation looks like:
figure();
triplot(DT, 'Color', 'k');
axis equal;
axis off;
We now have to identify the extra triangles we don't want and remove them. We can do this by finding the centroids of each triangle and using inpolygon to test if they are outside all 3 of our individual cuboid projections. We can then compute the areas of the remaining triangles and sum them up using polyarea, giving us the total area of the projection:
dtFaces = DT.ConnectivityList;
dtVertices = DT.Points;
meanX = mean(reshape(dtVertices(dtFaces, 1), size(dtFaces)), 2);
meanZ = mean(reshape(dtVertices(dtFaces, 2), size(dtFaces)), 2);
index = inpolygon(meanX, meanZ, xPoly{1}, zPoly{1});
for iPoly = 2:nPoly
index = index | inpolygon(meanX, meanZ, xPoly{iPoly}, zPoly{iPoly});
end
dtFaces = dtFaces(index, :);
xUnion = reshape(dtVertices(dtFaces, 1), size(dtFaces)).';
yUnion = reshape(dtVertices(dtFaces, 2), size(dtFaces)).';
totalArea = sum(polyarea(xUnion, yUnion));
And the total area for this example is:
totalArea =
9.970392341143055e+03
NOTE: The above code has been generalized for an arbitrary number of cuboids.
polyarea is the right way to go, but you need to call it on the convex hull of each projection. If not, you will have points in the centers of your projections and the result is not a "simple" polygon.

I am searching a loop which stores values in a matrix

I have an input-table. It has 3 columns and some rows -> The first column are my x-coordinates and the second column are my y-coordinates. (Of my start points)
This start point is always my left bottom corner point of my rectangle. From this point I want to draw my rectangle. (Height and width should be a constant). I have big problems with loops and matrices:
My output must be looking like:
AllPoints= [0,0;1,0;1,1;0,1;5,5;10,5;10,10;5,10;2,2;4,2;4,4;2,4];
-> Explanation see screenshot
[clc % löscht den Bildschirm
clear all % löscht alle Variablen
%Table -> (start Points...)
%12 0 10
%14 0 30
%16 0 54
%18 0 51
%20 0 35
%22 0 12
%14 2 25
%16 2 35
Input_Matrix = readtable('Testbeispiel_Rainflow.dat',...
'Delimiter','\t','ReadVariableNames',false)%,'Format','%f%f%f')][1]

Get rectangular block in matlab

For my project I need to get features for negative samples to train the classifier. I already had positive samples. Here is what I am trying to do.
root_dir = '/home/shahnawaz/Downloads/test';
data_set = 'training';
%% get label directory
cam = 2; % 2 = left color camera
label_dir = fullfile(root_dir,[data_set '/label_' num2str(cam)]);
nlabels = length(dir(fullfile(label_dir, '*.txt')));
%% main loop
img_idx=0;
count = 1;
for lab_idx = 1:1:nlabels
objects = readLabels(label_dir,lab_idx-1);
for a = 1 :1:length(objects)
s1 = objects(a).type;
s2 = 'Car';
cmp = strcmp(s1,s2);
rear = (objects(a).alpha >= -pi/2+0.07) | (objects(a).alpha <=-pi/2-0.07); % get car with rear portion
if (cmp )
%% write your code.
end
end
end
EDIT:
I have 7481 images with a resolution of 1224 * 370 and corresponding label files(annotation of objects in the image). From the label I get width = 423.81 - 387.63 = 37 and height = 203.12 - 181.54 = 22. I want to get a similar block excluding points 423.81 - 387.63 = 37 and 203.12 - 181.54 = 22 . Can someone help me do that. Here is the structure of the label file.
Truck 0.00 0 -1.57 599.41 156.40 629.75 189.25 2.85 2.63 12.34 0.47 1.49 69.44 -1.56
Car 0.00 0 1.85 387.63 181.54 423.81 203.12 1.67 1.87 3.69 -16.53 2.39 58.49 1.57
Cyclist 0.00 3 -1.65 676.60 163.95 688.98 193.93 1.86 0.60 2.02 4.59 1.32 45.84 -1.55
DontCare -1 -1 -10 503.89 169.71 590.61 190.13 -1 -1 -1 -1000 -1000 -1000 -10
DontCare -1 -1 -10 511.35 174.96 527.81 187.45 -1 -1 -1 -1000 -1000 -1000 -10
DontCare -1 -1 -10 532.37 176.35 542.68 185.27 -1 -1 -1 -1000 -1000 -1000 -10
DontCare -1 -1 -10 559.62 175.83 575.40 183.15 -1 -1 -1 -1000 -1000 -1000 -10
EDIT: I also have label file where I have more than one 'Car' object and where there is no 'Car' object. It is confusing me. Can some one sketch pseudo code
The 15 columns represent:
#Values Name Description
----------------------------------------------------------------------------
1 type Describes the type of object: 'Car', 'Van', 'Truck',
'Pedestrian', 'Person_sitting', 'Cyclist', 'Tram',
'Misc' or 'DontCare'
1 truncated Float from 0 (non-truncated) to 1 (truncated), where
truncated refers to the object leaving image boundaries
1 occluded Integer (0,1,2,3) indicating occlusion state:
0 = fully visible, 1 = partly occluded
2 = largely occluded, 3 = unknown
1 alpha Observation angle of object, ranging [-pi..pi]
4 bbox 2D bounding box of object in the image (0-based index):
contains left, top, right, bottom pixel coordinates
3 dimensions 3D object dimensions: height, width, length (in meters)
3 location 3D object location x,y,z in camera coordinates (in meters)
1 rotation_y Rotation ry around Y-axis in camera coordinates [-pi..pi]
1 score Only for results: Float, indicating confidence in
detection, needed for p/r curves, higher is better.

How to label data index with count using 3D histogram in Matlab

I have a set of data points (around 20000) with their x,y values and I want to remove the points that not very close to other points. I try to approach by 'digitizing' and I think the closest way to implement it in Matlab is a 3D histogram so I can remove the points in the low-count bins. I used hist3() but the problems is I couldn't get the index of the points labeled with counts (like the output 'ind' from histc()). The only way I can think of is a nested for loop which is the last thing I want to try. Is there any way I can label the points index or any other approach to do this?
Thanks
I feel like I need some clarification
I have the histogram graph from the data generated by #rayryeng
There are some bins have N=0 or N=1 so I want to remove the data in these bins.
For histc() there is a form of output [bincounts,ind]= histc( ) where ind returns the bin numbers the data falls into. So I can find the index of bins which less/equal or larger than 1, then find the data in the particular bins. Is there any similar thing I can do for a 2D inputs?
Thanks Again
hist3 should be able to accomplish this for you. I'm not quite sure where the problem is. You can call hist3 like so:
[N,C] = hist3(X);
This will automatically partition your dataset into a 10 x 10 grid of equally spaced containers. You can override this behaviour by doing:
[N,C] = hist3(X, NBINS);
NBINS is a 2 element array where the first element tells you how many bins you want vertically and the second element is how many bins you would like horizontally.
N will tell you how many elements fall within each location of the grid and C will give you a 1 x 2 cell array where the first element of the cell array gives you the X co-ordinates of each centre of the bin while the second element of the cell array gives you the Y co-ordinates of each centre of the bin.
To be explicit, if we have a 10 x 10 grid, C will contain a two element cell array where each element is 10 elements long. For each X co-ordinate of the centre found in C{1}, we will have 10 corresponding Y co-ordinates that relate to the a bin's centre in C{2}. This means that the first 10 bin centres are located at C{1}(1), C{2}(1), C{1}(1), C{2}(2), C{1}(1), C{2}(3), ..., C{1}(1), C{2}(10), then the next 10 bin centres are located at: C{1}(2), C{2}(1), C{1}(2), C{2}(2), C{1}(2), C{2}(3), ..., C{1}(1), C{2}(10).
As a quick example, let's do this on a grid between [0,1] on the x-axis and [0,1] on the y-axis. I'm going to generate 100 2D points. Let's also decompose the image into 10 bins horizontally and 10 bins vertically (as per the default of hist3).
rng(100); %// Set seed for reproducibility
A = rand(100,2);
[N,C] = hist3(A);
disp(N);
celldisp(C);
We thus get:
N =
1 2 0 1 2 0 1 0 1 1
0 1 1 1 1 1 0 0 2 5
0 4 1 1 1 1 1 4 0 1
2 0 3 2 2 1 1 0 2 1
0 0 0 0 1 1 1 0 0 1
1 1 1 2 1 1 0 2 0 1
1 0 2 1 2 0 3 1 1 1
0 1 0 0 0 1 1 0 0 1
1 0 1 2 3 3 0 0 0 2
0 2 1 1 0 1 0 3 0 1
C{1} =
Columns 1 through 7
0.0541 0.1528 0.2516 0.3503 0.4491 0.5478 0.6466
Columns 8 through 10
0.7453 0.8440 0.9428
C{2} =
Columns 1 through 7
0.0513 0.1510 0.2508 0.3505 0.4503 0.5500 0.6498
Columns 8 through 10
0.7495 0.8493 0.9491
This tells us that the first grid located at the top left corner of our point distribution only has 1 value logged into it. The next grid after that has 2 bins logged in it and so on and so forth. We also have our bin centres for each of the bins shown in C. Remember, We have 10 x 10 possible bin centres. If we want to display our data with the bin locations, this is what we can do:
[X,Y] = meshgrid(C{1},C{2});
plot(A(:,1), A(:,2), 'b*', X(:), Y(:), 'r*');
grid;
We thus get:
The red stars denote the bin centres while the blue stars denote our data points within the grid. Because our origin is on the bottom left corner of our plot, but the origin of the N matrix is at the top left corner (i.e. the first bin that is decomposed is at the top left while in our data it's at the bottom left corner), we need to rotate N by 90 degrees counter-clockwise so that the origins of each of the matrices agree with each other, and also agree with the plot. As such:
Nrot = rot90(N);
disp(Nrot);
Nrot =
1 5 1 1 1 1 1 1 2 1
1 2 0 2 0 0 1 0 0 0
0 0 4 0 0 2 1 0 0 3
1 0 1 1 1 0 3 1 0 0
0 1 1 1 1 1 0 1 3 1
2 1 1 2 1 1 2 0 3 0
1 1 1 2 0 2 1 0 2 1
0 1 1 3 0 1 2 0 1 1
2 1 4 0 0 1 0 1 0 2
1 0 0 2 0 1 1 0 1 0
As you can see from the picture, this agrees with what we see within the (rotated) N matrix as well as the bin centres C. Using N (or Nrot if you get the convention correct), you can now figure out which points to eliminate from your array of points. Any points that have low membership within N, you would find those points that are the closest to that bin centre that is associated to the grid location in N and remove them.
As an example, supposing that the bin in the first row, second column (of the rotated result) is the one you want to filter out. This corresponds to (C{1}(2), C{2}(10)). We also know that we need to filter out 5 points as they belong to this bin centre. Therefore:
numPointsToRemove = N(2,10); %//or Nrot(1,2);
%// Computes Euclidean distance between this bin centre with every point
dists = sqrt(sum(bsxfun(#minus, A, [C{1}(2) C{2}(10)]).^2, 2));
%// Find the numPointsToRemove closest points to the bin centre and remove
[~,ind] = sort(dists);
A(ind(1:numPointsToRemove,:)) = [];
We sort our distances in ascending order, then determine the numPointsToRemove closest points to this bin centre. We thus remove them from our data matrix.
If you want to remove those bins that have either a 0 or a 1 for the count, we can find those locations, then run a for loop and filter accordingly. However, any bins that have 0 means that we don't even need to run through and filter anything, because no points were mapped to there! You really need to filter out those values that have just 1 in the bins. In other words:
[rows, cols] = find(N == 1);
for index = 1 : numel(rows)
row = rows(index);
col = cols(index);
%// Computes Euclidean distance between this bin centre with every point
dists = sqrt(sum(bsxfun(#minus, A, [C{1}(row) C{2}(col)]).^2, 2));
%// Finds the closest point to the bin centre and remove
[~,ind] = min(dists);
A(ind,:) = [];
end
As you can see, this is similar the same procedure as above. As we wish to filter out those bins that only have 1 assigned to a bin, we just need to find the minimum distance. Remember, we don't need to process any bins that have a count of 0 so we can skip those.