Octopus
maxwell_function.F90
Go to the documentation of this file.
1!! Copyright (C) 2019 R. Jestaedt, H. Appel, F. Bonafe, M. Oliveira, N. Tancogne-Dejean
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
26 use iso_c_binding
27 use debug_oct_m
28 use fft_oct_m
29 use global_oct_m
30 use io_oct_m
32 use math_oct_m
33 use mpi_oct_m
34 use parser_oct_m
37 use string_oct_m
38 use unit_oct_m
41
42 implicit none
43
44 public :: &
45 mxf_t, &
46 mxf_init, &
52 mxf, &
53 mxf_read, &
55
56 integer, public, parameter :: &
57 MXF_EMPTY = 10001, &
58 mxf_const_wave = 10002, &
59 mxf_const_phase = 10004, &
60 mxf_gaussian_wave = 10005, &
61 mxf_cosinoidal_wave = 10006, &
62 mxf_logistic_wave = 10007, &
63 mxf_trapezoidal_wave = 10008, &
64 mxf_from_file = 10009, &
65 mxf_numerical = 10010, &
66 mxf_from_expr = 10011, &
67 mxf_fourier_series = 10012, &
68 mxf_zero_fourier = 10013
69
70 type mxf_t
71 integer :: mode = mxf_empty
72 real(real64) :: k_vector(3) = m_zero
73 real(real64) :: r0(3) = m_zero
74 real(real64) :: width = m_zero
75 real(real64) :: a0 = m_zero
76 real(real64) :: dx = m_zero
77 real(real64) :: init_x = m_zero
78 real(real64) :: final_x = m_zero
79 real(real64) :: growth = m_zero
80 integer :: niter = 0
81 integer :: nfreqs = 0
82
83 type(spline_t) :: amplitude
84 character(len=200) :: expression
85 type(fft_t) :: fft_handler
86 end type mxf_t
87
88 interface mxf
89 module procedure mxf_eval
90 end interface mxf
91
92contains
93
94 !------------------------------------------------------------
96 subroutine mxf_read(f, namespace, function_name, ierr)
97 type(mxf_t), intent(inout) :: f
98 type(namespace_t), intent(in) :: namespace
99 character(len=*), intent(in) :: function_name
100 integer, intent(out) :: ierr
101
102 type(block_t) :: blk
103 integer :: nrows, ncols, i, function_type, idim
104 character(len=100) :: row_name, function_expression
105 real(real64) :: a0, r0(3), growth, width, k_vector(3)
106
107 push_sub(mxf_read)
108
109 !%Variable MaxwellFunctions
110 !%Type block
111 !%Section Maxwell
112 !%Description
113 !% This block specifies the shape of a "spatial-dependent function", such as the
114 !% envelope needed when using the <tt>MaxwellFunctions</tt> block. Each line in the block
115 !% specifies one function. The first element of each line will be a string
116 !% that defines the name of the function. The second element specifies which type
117 !% of function we are using; in the following we provide an example for each of the
118 !% possible types. In the following, we will use</br>
119 !% <math>
120 !% \mathbf{r} = \begin{pmatrix} {\rm x} \\\\ {\rm y} \\\\ {\rm z} \end{pmatrix},
121 !% \mathbf{r}_0 = \begin{pmatrix} {\rm x0} \\\\ {\rm y0} \\\\ {\rm z0} \end{pmatrix},
122 !% \mathbf{k} = \begin{pmatrix} {\rm kx} \\\\ {\rm ky} \\\\ {\rm kz} \end{pmatrix},
123 !% w = {\rm width},
124 !% g = {\rm growth}
125 !% </math>
126 !%Option mxf_const_wave 10002
127 !%
128 !% <tt>%MaxwellFunctions
129 !% <br>&nbsp;&nbsp; "function-name" | mxf_const_wave | kx | ky | kz | x0 | y0 | z0
130 !% <br>%</tt>
131 !%
132 !% The function is constant plane wave <math> f(\mathbf{r}) = \cos( \mathbf{k} (\mathbf{r} - \mathbf{r}_0) ) </math>
133 !%
134 !%Option mxf_const_phase 10004
135 !%
136 !% <tt>%MaxwellFunctions
137 !% <br>&nbsp;&nbsp; "function-name" | mxf_const_phase | kx | ky | kz | x0 | y0 | z0
138 !% <br>%</tt>
139 !%
140 !% The function is a constant phase of <math> f(\mathbf{r}) = (\mathbf{k} \mathbf{r}_0) </math>
141 !%
142 !%Option mxf_gaussian_wave 10005
143 !%
144 !% <tt>%MaxwellFunctions
145 !% <br>&nbsp;&nbsp; "function-name" | mxf_gaussian_wave | kx | ky | kz | x0 | y0 | z0 | width
146 !% <br>%</tt>
147 !%
148 !% The function is a Gaussian,
149 !% <math> f(\mathbf{r}) = \exp( -( \mathbf{k} (\mathbf{r}-\mathbf{r}_0) )^2 / (2 {w}^2) ) </math>
150 !%
151 !%Option mxf_cosinoidal_wave 10006
152 !%
153 !% <tt>%MaxwellFunctions
154 !% <br>&nbsp;&nbsp; "function-name" | mxf_cosinoidal_wave | kx | ky | kz | x0 | y0 | z0 | width
155 !% <br>%</tt>
156 !%
157 !% <math>
158 !% f(\mathbf{r}) =
159 !% \begin{cases}
160 !% \cos( \frac{\pi}{2} \frac{ \mathbf{k}(\mathbf{r}-\mathbf{r}_0) - 2 w}{w} + \pi )
161 !% & \text{if } | \mathbf{k}(\mathbf{r}-\mathbf{r}_0) | \le w \\\\
162 !% 0 & \text{otherwise}
163 !% \end{cases}
164 !% </math>
165 !%
166 !%Option mxf_logistic_wave 10007
167 !%
168 !% <tt>%MaxwellFunctions
169 !% <br>&nbsp;&nbsp; "function-name" | mxf_logistic_wave | kx | ky | kz | x0 | y0 | z0 | growth | width
170 !% <br>%</tt>
171 !%
172 !% The function is a logistic function, <br>
173 !% <math>
174 !% f(\mathbf{r}) =
175 !% \left( \frac{1}{1 + e^{g \left( \frac{\mathbf{k} \cdot (\mathbf{r-r_0})}{|\mathbf{k}|} + \frac{w}{2} \right)}} \right)
176 !% \cdot
177 !% \left( \frac{1}{1 + e^{-g \left( \frac{\mathbf{k} \cdot (\mathbf{r-r_0})}{|\mathbf{k}|} - \frac{w}{2} \right)}} \right)
178 !% \cdot
179 !% {\left(1 + e^{\frac{g \cdot w}{2}}\right)}^2
180 !% </math></br>
181 !%
182 !%Option mxf_trapezoidal_wave 10008
183 !%
184 !% <tt>%MaxwellFunctions
185 !% <br>&nbsp;&nbsp; "function-name" | mxf_trapezoidal_wave | kx | ky | kz | x0 | y0 | z0 | growth | width
186 !% <br>%
187 !% </tt>
188 !%
189 !% The function is a logistic function,
190 !% <br>
191 !% <math>
192 !% f(\mathbf{r}) =
193 !% \begin{cases}
194 !% 0 & \text{if }
195 !% \mathbf{k} \cdot (\mathbf{r} - \mathbf{r}_0) / |\mathbf{k}| \leq -\frac{w}{2} \\\\
196 !% 1 & \text{if }
197 !% -\frac{w}{2} + \frac{1}{g} < \mathbf{k} \cdot (\mathbf{r} - \mathbf{r}_0) / |\mathbf{k}| < \frac{w}{2} - \frac{1}{g} \\\\
198 !% 1 - g\left[\mathbf{k} \cdot (\mathbf{r} - \mathbf{r}_0) / |\mathbf{k}| - \left(\frac{w}{2} - \frac{1}{g}\right)\right] &
199 !% \text{if } \frac{w}{2} - \frac{1}{g} \leq \mathbf{k} \cdot (\mathbf{r} - \mathbf{r}_0) / |\mathbf{k}| < \frac{w}{2} \\\\
200 !% 0 &
201 !% \text{if } \mathbf{k} \cdot (\mathbf{r} - \mathbf{r}_0) / |\mathbf{k}| \geq \frac{w}{2}
202 !% \end{cases}
203 !% </math></br>
204 !%Option mxf_from_expr 10011
205 !%
206 !% <tt>%MaxwellFunctions
207 !% <br>&nbsp;&nbsp; "function-name" | mxf_from_expr | kx | ky | kz | "expression"
208 !% <br>%</tt>
209 !%
210 !% The temporal shape of the field is given as an expression (e.g., <tt>cos(2.0*x-3*y+4*z)</tt>. The
211 !% letter <i>x</i>, <i>y</i>, <i>z</i> means spatial coordinates, obviously.
212 !% The expression is used to construct the function <i>f</i>
213 !% that defines the field.
214 !%End
215 ierr = -3
216 if (parse_block(namespace, 'MaxwellFunctions', blk) /= 0) then
217 ierr = -1
218 pop_sub(mxf_read)
219 return
220 end if
221
222 nrows = parse_block_n(blk)
223 row_loop: do i = 1, nrows
224 call parse_block_string(blk, i-1, 0, row_name)
225 if (trim(row_name) == trim(function_name)) then
226
227 ncols = parse_block_cols(blk, i-1)
228 call parse_block_integer(blk, i-1, 1, function_type)
229
230 a0 = m_one
231 r0 = m_zero
232 width = m_zero
233 k_vector = m_zero
234 select case (function_type)
235 case (mxf_const_wave)
236 do idim = 1, 3
237 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
238 end do
239 do idim = 1, 3
240 call parse_block_float(blk, i-1, 4+idim, r0(idim), units_inp%length)
241 end do
242 call mxf_init_const_wave(f, a0, k_vector, r0)
243 case (mxf_const_phase)
244 do idim = 1, 3
245 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
246 end do
247 do idim = 1, 3
248 call parse_block_float(blk, i-1, 4+idim, r0(idim), units_inp%length)
249 end do
250 call mxf_init_const_phase(f, a0, k_vector, r0)
251 case (mxf_gaussian_wave)
252 do idim = 1, 3
253 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
254 end do
255 do idim = 1, 3
256 call parse_block_float(blk, i-1, 4+idim, r0(idim), units_inp%length)
257 end do
258 call parse_block_float(blk, i-1, 8, width, units_inp%length)
259 call mxf_init_gaussian_wave(f, a0, k_vector, r0, width)
261 do idim = 1, 3
262 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
263 end do
264 do idim = 1, 3
265 call parse_block_float(blk, i-1, 4+idim, r0(idim), units_inp%length)
266 end do
267 call parse_block_float(blk, i-1, 8, width, units_inp%length)
268 call mxf_init_cosinoidal_wave(f, a0, k_vector, r0, width)
269 case (mxf_logistic_wave)
270 do idim = 1, 3
271 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
272 end do
273 do idim = 1, 3
274 call parse_block_float(blk, i-1, 4+idim, r0(idim), units_inp%length)
275 end do
276 call parse_block_float(blk, i-1, 8, growth, units_inp%length)
277 call parse_block_float(blk, i-1, 9, width, units_inp%length)
278 call mxf_init_logistic_wave(f, a0, k_vector, r0, growth, width)
280 do idim = 1, 3
281 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
282 end do
283 do idim = 1, 3
284 call parse_block_float(blk, i-1, 4+idim, r0(idim), units_inp%length)
285 end do
286 call parse_block_float(blk, i-1, 8, growth, units_inp%length)
287 call parse_block_float(blk, i-1, 9, width, units_inp%length)
288 call mxf_init_trapezoidal_wave(f, a0, k_vector, r0, growth, width)
289 case (mxf_from_expr)
290 do idim = 1, 3
291 call parse_block_float(blk, i-1, 1+idim, k_vector(idim), unit_one/units_inp%length)
292 end do
293 call parse_block_string(blk, i-1, 5, function_expression)
294 call conv_to_c_string(function_expression)
295 call mxf_init_fromexpr(f, k_vector, trim(function_expression))
296 case default
297 ierr = -2
298 call parse_block_end(blk)
299 pop_sub(mxf_read)
300 return
301 end select
302
303 ierr = 0
304 exit row_loop
305 end if
306 end do row_loop
307
308 call parse_block_end(blk)
309
310 pop_sub(mxf_read)
311 end subroutine mxf_read
312 !------------------------------------------------------------
313
314
315 !------------------------------------------------------------
316 subroutine mxf_init(f)
317 type(mxf_t), intent(inout) :: f
318
319 push_sub(mxf_init)
320
321 f%mode = mxf_empty
322 f%niter = 0
323 f%dx = m_zero
324
325 pop_sub(mxf_init)
326 end subroutine mxf_init
327 !------------------------------------------------------------
328
329
330 !------------------------------------------------------------
331 logical function mxf_is_empty(f)
332 type(mxf_t), intent(in) :: f
333
334 push_sub(mxf_is_empty)
335 mxf_is_empty = (f%mode == mxf_empty)
336
337 pop_sub(mxf_is_empty)
338 end function mxf_is_empty
339 !------------------------------------------------------------
340
341
342 !------------------------------------------------------------
343 subroutine mxf_init_const_wave(f, a0, k_vector, r0)
344 type(mxf_t), intent(inout) :: f
345 real(real64), intent(in) :: a0, k_vector(3), r0(3)
346
347 push_sub(mxf_init_const_wave)
348
349 f%mode = mxf_const_wave
350 f%a0 = a0
351 f%k_vector = k_vector
352 f%r0 = r0
353
354 pop_sub(mxf_init_const_wave)
355 end subroutine mxf_init_const_wave
356 !------------------------------------------------------------
357
358
359 !------------------------------------------------------------
360 subroutine mxf_init_const_phase(f, a0, k_vector, r0)
361 type(mxf_t), intent(inout) :: f
362 real(real64), intent(in) :: a0, k_vector(3), r0(3)
363
364 push_sub(mxf_init_const_phase)
365
366 f%mode = mxf_const_phase
367 f%a0 = a0
368 f%k_vector = k_vector
369 f%r0 = r0
370
371 pop_sub(mxf_init_const_phase)
372 end subroutine mxf_init_const_phase
373 !------------------------------------------------------------
374
375
376 !------------------------------------------------------------
377 subroutine mxf_init_gaussian_wave(f, a0, k_vector, r0, width)
378 type(mxf_t), intent(inout) :: f
379 real(real64), intent(in) :: a0, k_vector(3), r0(3), width
380
381 push_sub(mxf_init_gaussian_wave)
382
383 f%mode = mxf_gaussian_wave
384 f%a0 = a0
385 f%k_vector = k_vector
386 f%r0 = r0
387 f%width = width
388
390 end subroutine mxf_init_gaussian_wave
391 !------------------------------------------------------------
392
393
394 !------------------------------------------------------------
395 subroutine mxf_init_cosinoidal_wave(f, a0, k_vector, r0, width)
396 type(mxf_t), intent(inout) :: f
397 real(real64), intent(in) :: a0, k_vector(3), r0(3), width
398
400
402 f%a0 = a0
403 f%k_vector = k_vector
404 f%r0 = r0
405 f%width = width
406
408 end subroutine mxf_init_cosinoidal_wave
409 !------------------------------------------------------------
410
411
412 !------------------------------------------------------------
413 subroutine mxf_init_logistic_wave(f, a0, k_vector, r0, growth, width)
414 type(mxf_t), intent(inout) :: f
415 real(real64), intent(in) :: a0, k_vector(3), r0(3), growth, width
416
417 push_sub(mxf_init_logistic_wave)
418
419 f%mode = mxf_logistic_wave
420 f%a0 = a0
421 f%k_vector = k_vector
422 f%r0 = r0
423 f%growth = growth
424 f%width = width
425
427 end subroutine
428 !------------------------------------------------------------
429
430
431 !------------------------------------------------------------
432 subroutine mxf_init_trapezoidal_wave(f, a0, k_vector, r0, growth, width)
433 type(mxf_t), intent(inout) :: f
434 real(real64), intent(in) :: a0, k_vector(3), r0(3), growth, width
435
437
439 f%a0 = a0
440 f%k_vector = k_vector
441 f%r0 = r0
442 f%growth = growth
443 f%width = width
444
446 end subroutine
447 !------------------------------------------------------------
448
449
450 !------------------------------------------------------------
451 subroutine mxf_init_fromexpr(f, k_vector, expression)
452 type(mxf_t), intent(inout) :: f
453 real(real64), intent(in) :: k_vector(3)
454 character(len=*), intent(in) :: expression
455
456 push_sub(mxf_init_fromexpr)
457
458 f%mode = mxf_from_expr
459 f%k_vector = k_vector
460 f%expression = trim(expression)
461
462 pop_sub(mxf_init_fromexpr)
463 end subroutine mxf_init_fromexpr
464 !------------------------------------------------------------
465
470 !------------------------------------------------------------
471 complex(real64) function mxf_envelope_eval(f, x) result(env)
472 type(mxf_t), intent(in) :: f
473 real(real64), intent(in) :: x(:)
474 real(real64) :: xx, limit_1, limit_2, limit_3, limit_4, r_re, r_im, rr
475 complex(real64) :: r
476 integer :: xdim
477
478 xdim = size(x)
479
480 select case (f%mode)
481 case (mxf_const_wave)
482
483 env = f%a0
484
485 case (mxf_const_phase)
486
487 env = f%a0 * sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim)))
489 case (mxf_gaussian_wave)
490
491 r = exp(-((sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))) &
492 / norm2(f%k_vector(1:xdim)) )**2 / (m_two*f%width**2)))
493 env = f%a0 * r
494
496
497 r = m_zero
498 if (abs( sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))/norm2(f%k_vector(1:xdim)))) <= f%width) then
499 r = - cos((m_pi/m_two) * ((sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))) &
500 / norm2(f%k_vector(1:xdim)) - m_two*f%width) / f%width))
501 end if
502 env = f%a0 * r
503
504 case (mxf_logistic_wave)
505
506 r = m_one/(m_one + exp(f%growth*(sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))) &
507 / norm2(f%k_vector(1:xdim)) - f%width/m_two))) &
508 + m_one/(m_one + exp(-f%growth*(sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))) &
509 / norm2(f%k_vector(1:xdim)) + f%width/m_two))) - m_one
510 env = f%a0 * r
511
513
514 xx = sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))) / norm2(f%k_vector(1:xdim))
515 limit_1 = - f%width/m_two - m_one/f%growth
516 limit_2 = - f%width/m_two
517 limit_3 = f%width/m_two
518 limit_4 = f%width/m_two + m_one/f%growth
519 if ((xx > limit_1) .and. (xx <= limit_2)) then
520 r = m_one + f%growth * (sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim)))/norm2(f%k_vector(1:xdim)) + f%width/m_two)
521 else if ((xx > limit_2) .and. (xx <= limit_3)) then
522 r = m_one
523 else if ((xx > limit_3) .and. (xx <= limit_4)) then
524 r = m_one - f%growth * (sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim)))/norm2(f%k_vector(1:xdim)) - f%width/m_two)
525 else
526 r = m_zero
527 end if
528 env = f%a0 * r
529
530 case (mxf_from_expr)
531 ! here x(:) is actually x(:) - v(:)*t
532 rr = norm2(x)
533 call parse_expression(r_re, r_im, 3, x(:), rr, m_zero, trim(f%expression))
534 env = cmplx(r_re, r_im, real64)
535
536 case default
537
538 env = m_zero
539
540 end select
541
542 end function mxf_envelope_eval
543 !------------------------------------------------------------
551 !------------------------------------------------------------
552 complex(real64) function mxf_eval(f, x, phi) result(y)
553 type(mxf_t), intent(in) :: f
554 real(real64), intent(in) :: x(:)
555 real(real64), optional, intent(in) :: phi
556
557 real(real64) :: phi_
558 integer :: xdim
559
560 ! no push_sub because it is called too frequently
561
562 phi_ = optional_default(phi, m_zero)
563
564 xdim = size(x)
565
566 y = mxf_envelope_eval(f, x)
567 if (f%mode /= mxf_const_phase) then
568 y = y * exp(m_zi * (sum(f%k_vector(1:xdim)*(x(:) - f%r0(1:xdim))) + phi_))
569 endif
570
571 end function mxf_eval
572 !------------------------------------------------------------
573
574end module maxwell_function_oct_m
575
576!! Local Variables:
577!! mode: f90
578!! coding: utf-8
579!! End:
double exp(double __x) __attribute__((__nothrow__
double cos(double __x) __attribute__((__nothrow__
Fast Fourier Transform module. This module provides a single interface that works with different FFT ...
Definition: fft.F90:118
real(real64), parameter, public m_two
Definition: global.F90:190
real(real64), parameter, public m_zero
Definition: global.F90:188
real(real64), parameter, public m_pi
some mathematical constants
Definition: global.F90:186
complex(real64), parameter, public m_zi
Definition: global.F90:202
real(real64), parameter, public m_one
Definition: global.F90:189
Definition: io.F90:114
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:115
integer, parameter, public mxf_fourier_series
integer, parameter, public mxf_logistic_wave
complex(real64) function mxf_envelope_eval(f, x)
Evaluation of envelope itself.
complex(real64) function mxf_eval(f, x, phi)
Evaluation of spatial envelope Functions.
integer, parameter, public mxf_trapezoidal_wave
subroutine, public mxf_read(f, namespace, function_name, ierr)
This function initializes "f" from the MXFunctions block.
integer, parameter, public mxf_from_file
integer, parameter, public mxf_cosinoidal_wave
integer, parameter, public mxf_zero_fourier
subroutine, public mxf_init_const_wave(f, a0, k_vector, r0)
subroutine, public mxf_init(f)
integer, parameter, public mxf_numerical
subroutine mxf_init_trapezoidal_wave(f, a0, k_vector, r0, growth, width)
subroutine, public mxf_init_const_phase(f, a0, k_vector, r0)
integer, parameter, public mxf_gaussian_wave
integer, parameter, public mxf_const_wave
subroutine, public mxf_init_gaussian_wave(f, a0, k_vector, r0, width)
logical function, public mxf_is_empty(f)
subroutine, public mxf_init_fromexpr(f, k_vector, expression)
integer, parameter, public mxf_const_phase
subroutine, public mxf_init_cosinoidal_wave(f, a0, k_vector, r0, width)
integer, parameter, public mxf_from_expr
subroutine mxf_init_logistic_wave(f, a0, k_vector, r0, growth, width)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:618
subroutine, public conv_to_c_string(str)
converts to c string
Definition: string.F90:252
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:132
This module defines the unit system, used for input and output.
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
static double f(double w, void *p)