Skip to content

Commit afc87aa

Browse files
committed
Merge pull request ComputationalRadiationPhysics#851 from PrometheusPi/fix-phasePlaneWave
avoid non zero E-field integral in plane wave
2 parents 78e5cc6 + 323c76f commit afc87aa

File tree

1 file changed

+46
-25
lines changed

1 file changed

+46
-25
lines changed

src/picongpu/include/fields/laserProfiles/laserPlaneWave.hpp

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@
1919
*/
2020

2121

22-
23-
#ifndef LASERPLANEWAVE_HPP
24-
#define LASERPLANEWAVE_HPP
22+
#pragma once
2523

2624
#include "types.h"
2725
#include "simulation_defines.hpp"
@@ -30,13 +28,38 @@ namespace picongpu
3028
{
3129
/** plane wave (use periodic boundaries!)
3230
*
33-
* no phase shifts, no spacial envelope
31+
* no transverse spacial envelope
32+
* based on the electric potential
33+
* Phi = Phi_0 * exp(0.5 * (x-x_0)^2 / sigma^2) * cos(k*(x - x_0) - phi)
34+
* by applying -grad Phi = -d/dx Phi = E(x)
35+
* we get:
36+
* E = -Phi_0 * exp(0.5 * (x-x_0)^2 / sigma^2) * [k*sin(k*(x - x_0) - phi) + x/sigma^2 * cos(k*(x - x_0) - phi)]
37+
*
38+
* This approach ensures that int_{-infinity}^{+infinity} E(x) = 0 for any phase
39+
* if we have no transverse profile as we have with this plane wave train
40+
*
41+
* Since PIConGPU requires a temporally defined electric field, we use:
42+
* t = x/c and (x-x_0)/sigma = (t-t_0)/tau and k*(x-x_0) = omega*(t-t_0) with omega/k = c and tau * c = sigma
43+
* and get:
44+
* E = -Phi_0*omega/c * exp(0.5 * (t-t_0)^2 / tau^2) * [sin(omega*(t - t_0) - phi) + t/(omega*tau^2) * cos(omega*(t - t_0) - phi)]
45+
* and define:
46+
* E_0 = -Phi_0*omega/c
47+
* integrationCorrectionFactor = t/(omega*tau^2)
48+
*
49+
* Please consider:
50+
* 1) The above formulae does only apply to a Gaussian envelope. If the plateau length is
51+
* not zero, the integral over the volume will only vanish if the plateau length is
52+
* a multiple of the wavelength.
53+
* 2) Since we define our envelope by a sigma of the laser intensity,
54+
* tau = PULSE_LENGTH / sqrt(2)
3455
*/
3556
namespace laserPlaneWave
3657
{
37-
38-
/** Compute the
58+
/** calculates longitudinal field distribution
3959
*
60+
* @param currentStep
61+
* @param phase
62+
* @return
4063
*/
4164
HINLINE float3_X laserLongitudinal( uint32_t currentStep, float_X& phase )
4265
{
@@ -46,48 +69,50 @@ namespace picongpu
4669
double envelope = double(AMPLITUDE );
4770
float3_X elong(float3_X::create(0.0));
4871

49-
// a NON-symmetric (starting with phase=0) pulse will be initialized at position z=0 for
50-
// a time of RAMP_INIT * PULSE_LENGTH + LASER_NOFOCUS_CONSTANT = INIT_TIME.
51-
// we shift the complete pulse for the half of this time to start with
52-
// the front of the laser pulse.
5372
const double mue = 0.5 * RAMP_INIT * PULSE_LENGTH;
5473

5574
const double w = 2.0 * PI * f;
75+
const double tau = PULSE_LENGTH / sqrt( 2.0 );
5676

5777
const double endUpramp = mue;
5878
const double startDownramp = mue + LASER_NOFOCUS_CONSTANT;
5979

60-
80+
double integrationCorrectionFactor = 0.0;
6181

6282
if( runTime > startDownramp )
6383
{
6484
// downramp = end
65-
const double exponent =
66-
( ( runTime - startDownramp )
67-
/ PULSE_LENGTH / sqrt( 2.0 ) );
85+
const double exponent = (runTime - startDownramp) / tau;
6886
envelope *= exp( -0.5 * exponent * exponent );
87+
integrationCorrectionFactor = ( runTime - startDownramp )/ (w*tau*tau);
6988
}
7089
else if ( runTime < endUpramp )
7190
{
7291
// upramp = start
73-
const double exponent = ( ( runTime - endUpramp ) / PULSE_LENGTH / sqrt( 2.0 ) );
92+
const double exponent = (runTime - endUpramp) / tau;
7493
envelope *= exp( -0.5 * exponent * exponent );
75-
94+
integrationCorrectionFactor = ( runTime - endUpramp )/ (w*tau*tau);
7695
}
7796

7897
const double timeOszi = runTime - endUpramp;
98+
const double t_and_phase = w * timeOszi + LASER_PHASE;
99+
// to understand both components [sin(...) + t/tau^2 * cos(...)] see description above
79100
if( Polarisation == LINEAR_X )
80101
{
81-
elong.x() = float_X( envelope * math::sin( w * timeOszi + LASER_PHASE));
102+
elong.x() = float_X( envelope * (math::sin(t_and_phase)
103+
+ math::cos(t_and_phase) * integrationCorrectionFactor));
82104
}
83105
else if( Polarisation == LINEAR_Z)
84106
{
85-
elong.z() = float_X( envelope * math::sin( w * timeOszi + LASER_PHASE));
107+
elong.z() = float_X( envelope * (math::sin(t_and_phase)
108+
+ math::cos(t_and_phase) * integrationCorrectionFactor));
86109
}
87110
else if( Polarisation == CIRCULAR )
88111
{
89-
elong.x() = float_X( envelope / sqrt(2.0) * math::sin( w * timeOszi + LASER_PHASE));
90-
elong.z() = float_X( envelope / sqrt(2.0) * math::cos( w * timeOszi + LASER_PHASE));
112+
elong.x() = float_X( envelope / sqrt(2.0) * (math::sin(t_and_phase)
113+
+ math::cos(t_and_phase) * integrationCorrectionFactor));
114+
elong.z() = float_X( envelope / sqrt(2.0) * (math::cos(t_and_phase)
115+
- math::sin(t_and_phase) * integrationCorrectionFactor));
91116
}
92117

93118

@@ -96,7 +121,7 @@ namespace picongpu
96121
return elong;
97122
}
98123

99-
/**
124+
/** calculates transverse field distribution
100125
*
101126
* @param elong
102127
* @param phase
@@ -112,7 +137,3 @@ namespace picongpu
112137
}
113138
}
114139

115-
#endif /* LASERPLANEWAVE_HPP */
116-
117-
118-

0 commit comments

Comments
 (0)