<?xml version="1.0" encoding="utf-8"?>
<section version="5.0"
         xsi:schemaLocation="http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd"
         xml:id="particles.modifiers.compute_property"
         xmlns="http://docbook.org/ns/docbook"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xs="http://www.w3.org/2001/XMLSchema"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xmlns:xi="http://www.w3.org/2001/XInclude"
         xmlns:ns="http://docbook.org/ns/docbook">
  <title>Compute property</title>

  <para>
  
    <informalfigure><screenshot><mediaobject><imageobject>
       <imagedata fileref="images/modifiers/compute_property_panel.png" format="PNG" />
    </imageobject></mediaobject></screenshot></informalfigure>
  
  This modifier evaluates a user-defined mathematical expression for every particle 
  and assigns the results to a particle property. It can be used to assign new 
  properties to particles or to modify existing properties.</para>

  <para>
  The math formula specified by the user can depend on existing particle properties or global parameters such as the simulation box size or animation time. 
  The list of available input variables that can be referenced in the formula is displayed in the lower panel.
  </para> 
  
  <simplesect>
    <title>Output property</title>
  
  <para>OVITO differentiates between <emphasis>standard</emphasis> particle properties and <emphasis>custom</emphasis> particle properties.
  The properties of the former type have specific meanings to OVITO (e.g. <literal>Position</literal> or <literal>Particle Identifier</literal>) while custom properties
  have arbitrary, user-defined names (e.g. <literal>MyPropertyA</literal>) and the stored data is not interpreted by OVITO in any way.
  The <emphasis>Compute property</emphasis> modifier allows you to create or modify both types of particle properties. If you use the 
  modifier to assign values to certain standard properties such as <literal>Position</literal>, <literal>Color</literal>, or <literal>Radius</literal>,
  it will immediately affect the visual appearance of particles (see this <link linkend="howto.transparent_particles">example</link>).
  </para>
  
  <para>
  The list of all standard properties known to OVITO can be found in the <emphasis>Output property</emphasis> drop-down list. If you want to create a custom particle property,
  simply enter a name of your choice into the text field. Note that property names in OVITO are case-sensitive.
  </para>
  
  </simplesect>
  
  <simplesect>
    <title>Vector properties</title>
  
  <para>
  Some particle properties (e.g. <literal>Position</literal> or <literal>Color</literal>) are vector quantities, which consist of multiple components per particle. If you want to use the <emphasis>Compute property</emphasis>
  modifier to assign values to such a vector property, then you'll have to enter multiple math expressions, one for each vector component.
  Note that the modifier does not allow you to create custom properties with multiple vector components. 
  </para>
  
  </simplesect>
  
  <simplesect>
    <title>Conditional assignments</title>
  
  <para>
  If the particle property that you are computing already exists, then the existing values will be overwritten with the new ones 
  computed by the modifier. The <emphasis>Compute only for selected particles</emphasis> option, however, makes it possible to restrict the 
  assignment to a subset of particles and preserve the existing property values for unselected particles. 
  If the computed property did not exist before, then unselected particles will be assigned the default value 0 if this option is active.
  </para>
  
  <para>
  Furthermore, the ternary operator <literal>?:</literal> (see table below) allows you to make use of simple <emphasis>if-else</emphasis> conditions. For example, to make all particles
  in the upper half of the simulation box semi-transparent and the particles in the lower half fully opaque, use the following conditional expression to 
  compute the values of the <literal>Transparency</literal> particle property: 
  <programlisting>(ReducedPosition.Z &gt; 0.5) ? 0.7 : 0.0</programlisting>
  </para>
  
  <para>
  For more demanding computation or analysis tasks, which cannot be accomplished with static expressions, please 
  consider using the <link linkend="particles.modifiers.python_script">Python script</link> modifier, 
  which lets you write a modification function in a procedural programming language.
  </para>
  
  </simplesect>

  <simplesect>
    <title>Including neighbor particles</title>
    <para>By default the property value computed for a particle can only depend on other properties of the same particle (or global quantities).
    The <emphasis>Include neighbor terms</emphasis> options allows to also include nearby particles within a certain cutoff radius
    of the central particle when computing its property value. If this option is active, the final property value <emphasis>P(i)</emphasis> of a central particle <emphasis>i</emphasis> is computed
    as
    <screenshot><mediaobject><imageobject>
      <imagedata fileref="images/modifiers/compute_property_modifier_neighbor_formula.png" format="PNG" />
    </imageobject></mediaobject></screenshot>
    The first term, <emphasis>F(i)</emphasis>, is the first user-defined function, which is evaluated once for the central particle. 
    The second term consists of contributions from all neighbors within the cutoff radius <emphasis>R<subscript>c</subscript></emphasis>. Each contribution is determined by a second user-defined
    function, <emphasis>G(j)</emphasis>, which is evaluated for every neighbor particle <emphasis>j</emphasis>. The function <emphasis>G(j)</emphasis>
    must be entered into the input field <emphasis>Neighbor expression</emphasis>, and it may only depend on properties
    of the current neighbor and on global parameters. In addition it may depend on the distance of the neighbor from the central particle.
    </para>
    <para>
    This allows you to perform advanced computions that take into account the local neighborhood of particles. For example, we can
    average a particle property over a spherical volume around each particle by using the following expressions:
    <programlisting>F(i) := InputProperty / (NumNeighbors+1)
G(j) := InputProperty / (NumNeighbors+1)</programlisting>
    Note that <literal>NumNeighbors</literal> is a dynamic variable, which is queried in this example to normalize the resulting property value.
    We could even weight the contributions from different neighbors based on their distance from the central particle by incorporating the <literal>Distance</literal>
    dynamic variable in the function <emphasis>G(j)</emphasis>. For example, these expressions compute the potential energy according to a Lennard-Jones potential:
    <programlisting>F(i) := 0
G(j) := 4 * (Distance^-12 - Distance^-6)</programlisting>
    Here, no contribution is coming from the central particle.
    </para>
  </simplesect>
  
  <simplesect>
    <title>Parameters</title>

    <variablelist>
      <varlistentry>
        <term>Output property</term>
        <listitem>
          <para>Specifies the output property that receives the values computed by the modifier.
          You can either create a new property by entering a user-defined name in the field, or pick one of the <link
          linkend="usage.particle_properties">standard properties</link> from the drop-down list.</para>
        </listitem>
      </varlistentry>

      <varlistentry>
        <term>Compute only for selected particles</term>
        <listitem>
          <para>Restricts the evaluation of the math expression and the assignment of results to the subset of selected particles. 
          This option is useful if you want to selectively overwrite the property values of certain particles.</para>
        </listitem>
      </varlistentry>

    </variablelist>
  </simplesect>
            
  <simplesect>
    <title>Expression syntax</title>
    <para>          
   The expression syntax supported by the modifier is very
   similar to the one of the C programming language. Variable names and function names are case-sensitive.   
   Arithmetic expressions can be created from
   float literals, variables, or functions using the following operators
   in the given order of precedence: 
   <informaltable>
   <tgroup cols="2">
   <thead>
     <row>
       <entry>Operator</entry>
       <entry>Description</entry>
     </row>
   </thead>
       <tbody>
         <row>
           <entry>(...)</entry>

           <entry>expressions in parentheses are evaluated first</entry>
         </row>

         <row>
           <entry>A^B</entry>

           <entry>exponentiation (A raised to the power B)</entry>
         </row>

         <row>
           <entry>A*B, A/B</entry>

           <entry>multiplication and division</entry>
         </row>

         <row>
           <entry>A+B, A-B</entry>

           <entry>addition and subtraction</entry>
         </row>

         <row>
           <entry>A==B, A!=B, A&lt;B, A&lt;=B, A&gt;B, A&gt;=B</entry>

           <entry>comparison between A and B (result is either 0 or
           1)</entry>
         </row>

         <row>
           <entry>A &amp;&amp; B</entry>

           <entry>logical AND operator: result is 1 if A and B differ from
           0, else 0</entry>
         </row>

         <row>
           <entry>A || B</entry>

           <entry>logical OR operator: result is 1 if A or B differ from
           0, else 0</entry>
         </row>
         
         <row>
           <entry>A ? B : C</entry>
           <entry>If A differs from 0 (i.e. is true), the resulting value of this expression
           is B, else C.</entry>
         </row>
         
       </tbody></tgroup>
     </informaltable></para>

   <para>The expression parser supports the following functions:
   <informaltable>
   <tgroup cols="2">
   <thead>
     <row>
       <entry>Function name</entry>
       <entry>Description</entry>
     </row>
   </thead>
       <tbody>
         <row>
           <entry>abs(A)</entry>

           <entry>Absolute value of A. If A is negative, returns -A
           otherwise returns A.</entry>
         </row>

         <row>
           <entry>acos(A)</entry>

           <entry>Arc-cosine of A. Returns the angle, measured in radians,
           whose cosine is A.</entry>
         </row>

         <row>
           <entry>acosh(A)</entry>

           <entry>Same as acos() but for hyperbolic cosine.</entry>
         </row>

         <row>
           <entry>asin(A)</entry>

           <entry>Arc-sine of A. Returns the angle, measured in radians,
           whose sine is A.</entry>
         </row>

         <row>
           <entry>asinh(A)</entry>

           <entry>Same as asin() but for hyperbolic sine.</entry>
         </row>

         <row>
           <entry>atan(A)</entry>

           <entry>Arc-tangent of A. Returns the angle, measured in
           radians, whose tangent is A.</entry>
         </row>

         <row>
           <entry>atan2(Y,X)</entry>

           <entry>Two argument variant of the arctangent function. Returns
           the angle, measured in radians. This function is documented
           <link
           xlink:href="http://en.wikipedia.org/wiki/Atan2">here</link>.</entry>
         </row>

         <row>
           <entry>atanh(A)</entry>

           <entry>Same as atan() but for hyperbolic tangent.</entry>
         </row>

         <row>
           <entry>avg(A,B,...)</entry>

           <entry>Returns the average of all arguments.</entry>
         </row>

         <row>
           <entry>cos(A)</entry>

           <entry>Cosine of A. Returns the cosine of the angle A, where A
           is measured in radians.</entry>
         </row>

         <row>
           <entry>cosh(A)</entry>

           <entry>Same as cos() but for hyperbolic cosine.</entry>
         </row>

         <row>
           <entry>exp(A)</entry>

           <entry>Exponential of A. Returns the value of e raised to the
           power A where e is the base of the natural logarithm, i.e.
           the non-repeating value approximately equal to
           2.71828182846.</entry>
         </row>

         <row>
           <entry>fmod(A,B)</entry>
           <entry>Returns the floating-point remainder of A/B (rounded towards zero).</entry>
         </row>

         <row>
           <entry>rint(A)</entry>

           <entry>Rounds A to the closest integer. 0.5 is rounded to
           1.</entry>
         </row>

         <row>
           <entry>ln(A)</entry>

           <entry>Natural (base e) logarithm of A.</entry>
         </row>

         <row>
           <entry>log10(A)</entry>

           <entry>Base 10 logarithm of A.</entry>
         </row>

         <row>
           <entry>log2(A)</entry>

           <entry>Base 2 logarithm of A.</entry>
         </row>

         <row>
           <entry>max(A,B,...)</entry>

           <entry>Returns the maximum of all parameter values.</entry>
         </row>

         <row>
           <entry>min(A,B,...)</entry>

           <entry>Returns the minimum of all parameter values.</entry>
         </row>

         <row>
           <entry>sign(A)</entry>
           <entry>Returns: 1 if A is positive; -1 if A is negative; 0 if A is zero.</entry>
         </row>                

         <row>
           <entry>sin(A)</entry>

           <entry>Sine of A. Returns the sine of the angle A, where A is
           measured in radians.</entry>
         </row>

         <row>
           <entry>sinh(A)</entry>

           <entry>Same as sin() but for hyperbolic sine.</entry>
         </row>

         <row>
           <entry>sqrt(A)</entry>

           <entry>Square root of a value.</entry>
         </row>

         <row>
           <entry>sum(A,B,...)</entry>

           <entry>Returns the sum of all parameter values.</entry>
         </row>
         
         <row>
           <entry>tan(A)</entry>

           <entry>Tangent of A. Returns the tangent of the angle A, where
           A is measured in radians.</entry>
         </row>
       </tbody></tgroup>
     </informaltable>
     </para>
     <para> </para>
  </simplesect>

  <simplesect>
    <title>Example 1</title>
    <para>Our aim is to compute the linear velocity of each
    particle based on the components v<subscript>x</subscript>,
    v<subscript>y</subscript>, and v<subscript>z</subscript> of their velocity
    vectors. For this, we create a new user-defined property with the name "<literal>Speed</literal>". The following
    formula is entered into the expression field: <programlisting>sqrt(Velocity.X^2 + Velocity.Y^2 + Velocity.Z^2)</programlisting>
    Here we reference the X, Y, and Z components of the standard
    <literal>Velocity</literal> particle property, which must be present in the
    input dataset. The computed linear velocity property can 
    subsequently be used, for instance, to color particles with the <emphasis><link
    linkend="particles.modifiers.color_coding">Color Coding</link></emphasis>
    modifier.</para>
  </simplesect>

  <simplesect>
    <title>Example 2</title>
    <para>The <emphasis>Compute property</emphasis> modifier can also be used to set
    particle properties which are not accessible by other means. One such example is
    the per-particle radius: Let us assume we have already selected a subset of particles that 
    we want to give a different size.
    We can use the <emphasis>Compute property</emphasis> modifier to set
    the value of the <literal>Radius</literal> particle property, which determines the
    per-particle display radii. The selection state of particles is given by the
    <literal>Selection</literal> property. With the
    formula <programlisting>Selection ? 1.5 : 1.0</programlisting> we assign a
    radius that depends on the selection state of each particle, which can be either 1 or 0. 
    That is, the above radius expression will evaluate to 1.5 for selected particles, and to 1.0 for unselected
    particles.
    </para>
  </simplesect>
</section>
