AngleCmd.h 3.44 KB
Newer Older
1
2
////////////////////////////////////////////////////////////////////////////////
//
Francois Gygi's avatar
Francois Gygi committed
3
4
5
6
// Copyright (c) 2008 The Regents of the University of California
//
// This file is part of Qbox
//
Francois Gygi's avatar
Francois Gygi committed
7
8
// Qbox is distributed under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 2 of
Francois Gygi's avatar
Francois Gygi committed
9
10
11
12
13
14
// the License, or (at your option) any later version.
// See the file COPYING in the root directory of this distribution
// or <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
//
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// AngleCmd.h:
//
////////////////////////////////////////////////////////////////////////////////

#ifndef ANGLECMD_H
#define ANGLECMD_H

#include <iostream>
#include "UserInterface.h"
#include "Sample.h"
#include <cstdlib>

class AngleCmd : public Cmd
{
  public:

  Sample *s;

  AngleCmd(Sample *sample) : s(sample) {};

Francois Gygi's avatar
Francois Gygi committed
35
36
  const char *name(void) const { return "angle"; }
  const char *help_msg(void) const
37
  {
38
    return
39
    "\n angle\n\n"
Francois Gygi's avatar
Francois Gygi committed
40
41
42
43
    " syntax: angle [-pbc] name1 name2 name3\n\n"
    "   The angle command prints the angle defined by three atoms.\n"
    "   If the -pbc option is used, the angle is computed using the\n"
    "   nearest atoms taking into account periodic boundary conditions.\n\n";
44
45
46
47
  }

  int action(int argc, char **argv)
  {
Francois Gygi's avatar
Francois Gygi committed
48
    if ( ! ( argc == 4 || argc == 5 ) )
49
50
51
    {
      if ( ui->onpe0() )
      {
Francois Gygi's avatar
Francois Gygi committed
52
        cout << " use: angle [-pbc] name1 name2 name3" << endl;
53
54
55
      }
      return 1;
    }
56

Francois Gygi's avatar
Francois Gygi committed
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
    string name1, name2, name3;
    bool use_pbc = false;

    if ( argc == 4 )
    {
      name1 = argv[1];
      name2 = argv[2];
      name3 = argv[3];
    }
    if ( argc == 5 )
    {
      if ( strcmp(argv[1],"-pbc") )
      {
        if ( ui->onpe0() )
        {
          cout << " use: angle [-pbc] name1 name2 name3" << endl;
        }
        return 1;
      }
      use_pbc = true;
      name1 = argv[2];
      name2 = argv[3];
      name3 = argv[4];
    }

82
83
84
85
86
    Atom* a1 = s->atoms.findAtom(name1);
    Atom* a2 = s->atoms.findAtom(name2);
    Atom* a3 = s->atoms.findAtom(name3);
    if ( a1 == 0 || a2 == 0 || a3 == 0 )
    {
87
88
89
      if ( ui->onpe0() )
      {
        if ( a1 == 0 )
90
          cout << " AngleCmd: atom " << name1 << " not defined" << endl;
91
        if ( a2 == 0 )
92
          cout << " AngleCmd: atom " << name2 << " not defined" << endl;
93
        if ( a3 == 0 )
94
          cout << " AngleCmd: atom " << name3 << " not defined" << endl;
95
96
97
      }
      return 1;
    }
98
99
100

    if ( a1 == a2 || a2 == a3 || a3 == a1 )
    {
101
102
      if ( ui->onpe0() )
      {
103
104
        cout << " AngleCmd: replicated atoms in " << name1
             << " " << name2 << " " << name3 << endl;
105
106
107
      }
      return 1;
    }
108

Francois Gygi's avatar
Francois Gygi committed
109
    if ( ui->onpe0() )
110
    {
Francois Gygi's avatar
Francois Gygi committed
111
112
113
      D3vector r12(a1->position()-a2->position());
      D3vector r32(a3->position()-a2->position());
      if ( norm2(r12) == 0.0 || norm2(r32) == 0.0 )
114
      {
115
        cout << " AngleCmd: atoms are too close" << endl;
Francois Gygi's avatar
Francois Gygi committed
116
        return 1;
117
      }
118

Francois Gygi's avatar
Francois Gygi committed
119
120
121
122
123
124
125
126
127
      if ( use_pbc )
      {
        const UnitCell& cell = s->wf.cell();
        cell.fold_in_ws(r12);
        cell.fold_in_ws(r32);
      }
      const double sp = normalized(r12) * normalized(r32);
      const double c = max(-1.0,min(1.0,sp));
      const double a = (180.0/M_PI)*acos(c);
128
      cout.setf(ios::fixed,ios::floatfield);
129
      cout << " angle " << name1 << "-" << name2  << "-" << name3
130
131
           << ": "
           << setprecision(3)
132
           << a << " (deg)" << endl;
133
134
135
136
137
    }
    return 0;
  }
};
#endif