Using comparing methods in Comparator Interface
published by Pradeep on February 21, 2018
Java 8 introduced some new methods in Comparator interface. I was going through this interface to check all available methods in it and did some code experiments to understand some of them and thought comparing and thenComparing methods are very interesting. There are multiple comparing methods which can be used in various situations. I listed all comparing methods here:
//static comparing methods
static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)
static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)
static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor)
//default thenComparing methods
default Comparator<T> thenComparing(Comparator<? super T> other)
default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor)
default <U> Comparator<T> thenComparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)
default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor)
default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor)
default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor)
If you can understand how these comparing methods work then you can generate a comparator object with out implementing this interface. I will go through some examples so it will be easier to understand. Lets create a Student class and add couple of students to a List.
public class Student{
private int id;
private String grade;
private String firstName;
public Student(int id,String grade, String firstName) {
this.id = id;
this.grade = grade;
this.firstName = firstName;
}
public int getId() {
return id;
}
public String getGrade() {
return grade;
}
public String getFirstName() {
return firstName;
}
@Override
public String toString() {
return "[" + id + "-" + grade +
"-" + firstName +
']';
}
public static void main(String args[]){
List<Student> students = Arrays.asList(new Student(4,"B","Sandra"),
new Student(2,"A","Cary"),
new Student(5,"A","Ferne"),
new Student(3,"B","Donnell"),
new Student(1,"A","Ria"));
//sort students
students.sort((s1, s2) -> Integer.compare(s1.getId(), s2.getId()));
//display list of students
students.forEach(System.out::println);
}
}
In line number 37 we are passing Comparator implementation to sort method. In next section we will see how to generate it with out implementing Comparator interface.
Generate comparator using static comparing methods
In line number 37 of above example we implemented comparator which compares integers. Here we wrote basic compare logic but instead why can’t we just pass the field on which we want to compare? This is where static comparing methods will come into picture. Static comparing methods need key extractor so comparator can be generated based on that. If we need to compare integers then use below static method to generate comparator.
static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor)
To use this method we need to pass ToIntFunction. This is a functional interface and it has single method ‘applyAsInt’, See below for the declaration of this method:
int applyAsInt(T value)
If we want to sort based on id field of the student, which is an int then we can update line number 37 to:
students.sort(Comparator.comparingInts) → s.getId();
We are passing implementation of ToIntFunction to comparingInt method. comparingInt will get int value from ToIntFunction and creates comparator based on that. We can even use method reference to reduce the code size.
students.sort(Comparator.comparingInt(Student::getId));
Basic thing to understand is, instead of ‘how’ we mentioned ‘what’ by using comparingInt method. Like wise there are other overloaded methods to generate comparator for long and double values. What is the case if we have objects? then we can use below method.
static <T,U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor)
This method takes a function so we can return any object and Comparator will use natural sorting on it if it implements Comparable interface else it will give compilation error. I can use this method to sort students based on there first names. First name is a String and String implements Comparable so this method works fine.
students.sort(Comparator.comparing(Student::getFirstName));
There is another comparing method available to generate customized comparator which take comparator as second parameter.
static <T,U> Comparator<T> comparing(Function<? super T,? extends U> keyExtractor, Comparator<? super U> keyComparator)
Using this method we can pass custom comparator. In below example we passed case insensitive string comparator.
students.sort(Comparator.comparing(Student::getFirstName,String.CASE_INSENSITIVE_ORDER));
With this we covered all static comparing methods. Instead of writing our own comparing logic we just need to pass key extractors, so these methods will generate comparator for us.
Using thenComparing methods
If we want to do sort on multiple fields then we can use ‘thenComparing’ methods. These methods will return comparator, so we can chain multiple thenComparing methods to sort multiple fields. It is like applying sorting on multiple columns in a table. For example we can do sort on grade and then on first names of the students like below.
students.sort(Comparator.comparing(Student::getGrade)
.thenComparing(Student::getFirstName));
thenComparing comes with same set of overloaded methods as comparing methods so we can pass functions to extract keys.
Conclusion
With all the above examples hope you understood the usage of these methods. Please comment if anything is missing or need more explanation.


Book Chapters
- K. Hamidouche, W. Saad, M. Debbah, "Distributed Caching in C-RAN", Cloud Access Networks, Cambridge University Press, March 2017.
Journals
- K. Hamidouche, W. Saad, M. Debbah,M. T. Thai, Z. Han, "Contract-based Incentive Mechanism for LTE over Unlicensed Channels", IEEE Transactions on Communications, to appear, 2019.
- K. Hamidouche, W. Saad, M. Debbah, J. B Song, C. S. Hong, "The 5G Cellular Backhaul Management Dilemma: To Cache or to Serve", IEEE Transactions on Wireless Communications, vol. 16, no. 8, pp. 4866 - 4879, July 2017.
- K. Hamidouche, W. Saad, M. Debbah, "A Multi-Game Framework for Harmonized LTE-U and WiFi Coexistence over Unlicensed Bands", IEEE Wireless Communications Magazine, Special Issue on LTE in Unlicensed Spectrum, vol. 23, no. 6, pp. 62-69, 2016.
Conference proceedings
- M. Yousefvand, K. Hamidouche, N. B. Mandayam, "Learning-based Resource Optimization in Ultra Reliable Low Latency HetNets", IEEE Global Communications Conference, Puako, HI, USA, 2019.
- A Nooraiepour, K. Hamidouche, W. U. Bajwa, N. Mandayam, "How Secure are Multicarrier Communication Systems Against Signal Exploitation Attacks?", IEEE Military Communications Conference (MILCOM), Los Angeles, CA, USA, 2018.
- K. Hamidouche, A. Talebzadeh Kasgari, W. Saad, M. Bennis, M. Debbah, "Collaborative Artificial Intelligence (AI) for User-Cell Association in Ultra-Dense Cellular Systems", International Conference on Communications (ICC), Kansas City, USA, 2018.
- K. Hamidouche, W. Saad, M. Debbah, "Popular Matching Games for Correlation-aware Resource Allocation in the Internet of Things", Global Communications Conference (Globecom), Singapore, 2017.
- K. Hamidouche, W. Saad, M. Debbah, "Minority Games for Backhaul Management in Cache-Enabled Small Cell Networks", European Wireless, Workshop on Competitive and Cooperative Approached for 5G Networks, Dresden, Germany, 2017.
- K. Hamidouche, W. Saad, M. Debbah, "Multi-Games for LTE and WiFi Coexistence over Unlicensed Channels", International conference on Network Games, Control and Optimization, Avignon, France, 2016.
- K. Hamidouche, W. Saad, M. Debbah, "Breaking the Economic Barrier of Caching in Cellular Networks: Incentives and Contracts", IEEE Global Communications Conference, Washington, DC, USA, 2016.
- F. Shen, K. Hamidouche, E. Baştuğ, M. Debbah, "A Stackelberg Game for Incentive Proactive Caching Mechanisms in Wireless Networks", IEEE Global Communications Conference, Washington, DC, USA, 2016.
- K. Hamidouche, W. Saad, M. Debbah, V. H. Poor, "Mean-Field Games for Distributed Caching in Ultra-Dense Small Cell Networks", American Control Conference, Boston, USA, 2016.
- A. Abboud, E. Baştuğ, K. Hamidouche, M. Debbah, "Distributed Caching in 5G Networks: An Alternating Direction Method of Multipliers Approach", The 6th IEEE International Workshop on Signal Processing Advances in Wireless Communications, Stockholm, Sweden, June 2015.
- K. Hamidouche, W. Saad, and M. Debbah, "Many-to-Many Matching Games for Proactive Social-Caching in Wireless Small Cell Networks", WNC3 workshop, WiOpt, Hammamet, Tunisia, 2014.
Others
Workshops and Talks
- K. Hamidouche, W. Saad, M. Debbah, "Distributed Caching in Dense Small Cell Networks", IEEE Communication Theory Workshop, Dana Point, CA, USA, May 2015.
- E. Baştuğ, K. Hamidouche, W. Saad, and M. Debbah, "Centrality-Based Caching for Mobile Wireless Networks", 1st KuVS Workshop on Anticipatory Networks, Stuttgart, Germany, September 2014.
National Journals
- K. Hamidouche, E. Baştuğ, M. Bennis, and M. Debbah, "Le caching proactif dans les réseaux cellulaires 5G", La Revue de l'Electricité et de l'Electronique (REE), vol. 2014-4, 2014.
PhD Thesis and Slides
- Thesis manuscript, December 2, 2016, CentraleSupélec, Gif-sur-Yvette, France.
- Thesis slides, December 2, 2016, CentraleSupélec, Gif-sur-Yvette, France.


Next: copy-structure, Previous: Structures Dictionary, Up: Structures Dictionary
defstruct
name-and-options [documentation] {!slot-description}*
⇒ structure-name
name-and-options ::=structure-name | (structure-name [[!options]])
options ::=!conc-name-option | {!constructor-option}* | !copier-option | !include-option | !initial-offset-option | !named-option | !predicate-option | !printer-option | !type-option
conc-name-option ::=:conc-name | (:conc-name) | (:conc-name conc-name)
constructor-option ::=:constructor | (:constructor) | (:constructor constructor-name) | (:constructor constructor-name constructor-arglist)
copier-option ::=:copier | (:copier) | (:copier copier-name)
predicate-option ::=:predicate | (:predicate) | (:predicate predicate-name)
include-option ::=(:include included-structure-name {!slot-description}*)
printer-option ::=!print-object-option | !print-function-option
print-object-option ::=(:print-object printer-name) | (:print-object)
print-function-option ::=(:print-function printer-name) | (:print-function)
type-option ::=(:type type)
named-option ::=:named
initial-offset-option ::=(:initial-offset initial-offset)
slot-description ::=slot-name | (slot-name [slot-initform [[!slot-option]]])
slot-option ::=:type slot-type | :read-only slot-read-only-p
conc-name—a string designator.
constructor-arglist—a boa lambda list.
constructor-name—a symbol.
copier-name—a symbol.
included-structure-name—an already-defined structure name.
Note that a derived type is not permissible, even if it would expand into a structure name.
initial-offset—a non-negative integer.
predicate-name—a symbol.
printer-name—a function name or a lambda expression.
slot-name—a symbol.
slot-initform—a form.
slot-read-only-p—a generalized boolean.
structure-name—a symbol.
type—one of the type specifiers list, vector, or (vector size), or some other type specifier defined by the implementation to be appropriate.
documentation—a string; not evaluated.
defstruct defines a structured type, named structure-type, with named slots as specified by the slot-options.
defstruct defines readers for the slots and arranges for setf to work properly on such reader functions. Also, unless overridden, it defines a predicate named name-p, defines a constructor function named make-constructor-name, and defines a copier function named copy-constructor-name. All names of automatically created functions might automatically be declared inline (at the discretion of the implementation).
If documentation is supplied, it is attached to structure-name as a documentation string of kind structure,
and unless :type is used, the documentation is also attached to structure-name as a documentation string of kind type and as a documentation string to the class object for the class named structure-name.
defstruct defines a constructor function that is used to create instances of the structure created by defstruct. The default name is make-structure-name. A different name can be supplied by giving the name as the argument to the constructor option. nil indicates that no constructor function will be created.
After a new structure type has been defined, instances of that type normally can be created by using the constructor function for the type. A call to a constructor function is of the following form:
(constructor-function-name
slot-keyword-1 form-1
slot-keyword-2 form-2
...)
The arguments to the constructor function are all keyword arguments. Each slot keyword argument must be a keyword whose name corresponds to the name of a structure slot. All the keywords and forms are evaluated. If a slot is not initialized in this way, it is initialized by evaluating slot-initform in the slot description
at the time the constructor function is called.
If no slot-initform is supplied, the consequences are undefined if an attempt is later made to read the slot’s value before a value is explicitly assigned.
Each slot-initform supplied for a defstruct component, when used by the constructor function for an otherwise unsupplied component, is re-evaluated on every call to the constructor function.
The slot-initform is not evaluated unless it is needed in the creation of a particular structure instance. If it is never needed, there can be no type-mismatch error, even if the type of the slot is specified; no warning should be issued in this case.
For example, in the following sequence, only the last call is an error.
(defstruct person (name 007 :type string)) (make-person :name "James") (make-person)
It is as if the slot-initforms were used as initialization forms for the keyword parameters of the constructor function.
The symbols which name the slots must not be used by the implementation as the names for the lambda variables in the constructor function, since one or more of those symbols might have been proclaimed special or might be defined as the name of a constant variable. The slot default init forms are evaluated in the lexical environment in which the defstruct form itself appears and in the dynamic environment in which the call to the constructor function appears.
For example, if the form (gensym) were used as an initialization form, either in the constructor-function call or as the default initialization form in defstruct, then every call to the constructor function would call gensym once to generate a new symbol.
Each slot-description in defstruct can specify zero or more slot-options.
A slot-option consists of a pair of a keyword and a value (which is not a form to be evaluated, but the value itself). For example:
(defstruct ship (x-position 0.0 :type short-float) (y-position 0.0 :type short-float) (x-velocity 0.0 :type short-float) (y-velocity 0.0 :type short-float) (mass *default-ship-mass* :type short-float :read-only t))
This specifies that each slot always contains a short float, and that the last slot cannot be altered once a ship is constructed.
The available slot-options are:
This specifies that the contents of the slot is always of type type. This is entirely analogous to the declaration of a variable or function; it effectively declares the result type of the reader function. It is implementation-dependent whether the type is checked when initializing a slot or when assigning to it. Type is not evaluated; it must be a valid type specifier.
When x is true, this specifies that this slot cannot be altered; it will always contain the value supplied at construction time. setf will not accept the reader function for this slot. If x is false, this slot-option has no effect. X is not evaluated.
When this option is false or unsupplied, it is implementation-dependent whether the ability to write the slot is implemented by a setf function or a setf expander.
The following keyword options are available for use with defstruct. A defstruct option can be either a keyword or a list of a keyword and arguments for that keyword; specifying the keyword by itself is equivalent to specifying a list consisting of the keyword and no arguments. The syntax for defstruct options differs from the pair syntax used for slot-options. No part of any of these options is evaluated.
This provides for automatic prefixing of names of reader (or access) functions. The default behavior is to begin the names of all the reader functions of a structure with the name of the structure followed by a hyphen.
:conc-name supplies an alternate prefix to be used. If a hyphen is to be used as a separator, it must be supplied as part of the prefix. If :conc-name is nil or no argument is supplied, then no prefix is used; then the names of the reader functions are the same as the slot names. If a non-nil prefix is given, the name of the reader function for each slot is constructed by concatenating that prefix and the name of the slot, and interning the resulting symbol in the package that is current at the time the defstruct form is expanded.
Note that no matter what is supplied for :conc-name, slot keywords that match the slot names with no prefix attached are used with a constructor function. The reader function name is used in conjunction with setf. Here is an example:
(defstruct (door (:conc-name dr-)) knob-color width material) ⇒ DOOR (setq my-door (make-door :knob-color 'red :width 5.0)) ⇒ #S(DOOR :KNOB-COLOR RED :WIDTH 5.0 :MATERIAL NIL) (dr-width my-door) ⇒ 5.0 (setf (dr-width my-door) 43.7) ⇒ 43.7 (dr-width my-door) ⇒ 43.7
Whether or not the :conc-name option is explicitly supplied, the following rule governs name conflicts of generated reader (or accessor) names: For any structure type S_1 having a reader function named R for a slot named X_1 that is inherited by another structure type S_2 that would have a reader function with the same name R for a slot named X_2, no definition for R is generated by the definition of S_2; instead, the definition of R is inherited from the definition of S_1. (In such a case, if X_1 and X_2 are different slots, the implementation might signal a style warning.)
This option takes zero, one, or two arguments. If at least one argument is supplied and the first argument is not nil, then that argument is a symbol which specifies the name of the constructor function. If the argument is not supplied (or if the option itself is not supplied), the name of the constructor is produced by concatenating the string "MAKE-" and the name of the structure, interning the name in whatever package is current at the time defstruct is expanded. If the argument is provided and is nil, no constructor function is defined.
If :constructor is given as (:constructor name arglist), then instead of making a keyword driven constructor function, defstruct defines a "positional" constructor function, taking arguments whose meaning is determined by the argument’s position and possibly by keywords. Arglist is used to describe what the arguments to the constructor will be. In the simplest case something like (:constructor make-foo (a b c)) defines make-foo to be a three-argument constructor function whose arguments are used to initialize the slots named a, b, and c.
Because a constructor of this type operates "By Order of Arguments," it is sometimes known as a "boa constructor."
For information on how the arglist for a "boa constructor" is processed, see Boa Lambda Lists.
It is permissible to use the :constructor option more than once, so that you can define several different constructor functions, each taking different parameters.
[Reviewer Note by Barmar: What about (:constructor) and (:constructor nil). Should we worry about it?]
defstruct creates the default-named keyword constructor function only if no explicit :constructor options are specified, or if the :constructor option is specified without a name argument.
(:constructor nil) is meaningful only when there are no other :constructor options specified. It prevents defstruct from generating any constructors at all.
Otherwise, defstruct creates a constructor function corresponding to each supplied :constructor option. It is permissible to specify multiple keyword constructor functions as well as multiple "boa constructors".
This option takes one argument, a symbol, which specifies the name of the copier function. If the argument is not provided or if the option itself is not provided, the name of the copier is produced by concatenating the string "COPY-" and the name of the structure, interning the name in whatever package is current at the time defstruct is expanded. If the argument is provided and is nil, no copier function is defined.
The automatically defined copier function is a function of one argument,
which must be of the structure type being defined.
The copier function creates a fresh structure that has the same type as its argument, and that has the same component values as the original structure; that is, the component values are not copied recursively.
If the defstruct :type option was not used, the following equivalence applies:
(copier-name x) = (copy-structure (the structure-name x))
This option is used for building a new structure definition as an extension of another structure definition. For example:
(defstruct person name age sex)
To make a new structure to represent an astronaut that has the attributes of name, age, and sex, and functions that operate on person structures, astronaut is defined with :include as follows:
(defstruct (astronaut (:include person) (:conc-name astro-)) helmet-size (favorite-beverage 'tang))
:include causes the structure being defined to have the same slots as the included structure. This is done in such a way that the reader functions for the included structure also work on the structure being defined. In this example, an astronaut therefore has five slots: the three defined in person and the two defined in astronaut itself. The reader functions defined by the person structure can be applied to instances of the astronaut structure, and they work correctly. Moreover, astronaut has its own reader functions for components defined by the person structure. The following examples illustrate the use of astronaut structures:
(setq x (make-astronaut :name 'buzz :age 45. :sex t :helmet-size 17.5)) (person-name x) ⇒ BUZZ (astro-name x) ⇒ BUZZ (astro-favorite-beverage x) ⇒ TANG
(reduce #'+ astros :key #'person-age) ; obtains the total of the ages ; of the possibly empty ; sequence of astros
The difference between the reader functions person-name and astro-name is that person-name can be correctly applied to any person, including an astronaut, while astro-name can be correctly applied only to an astronaut. An implementation might check for incorrect use of reader functions.
At most one :include can be supplied in a single defstruct. The argument to :include is required and must be the name of some previously defined structure. If the structure being defined has no :type option, then the included structure must also have had no :type option supplied for it. If the structure being defined has a :type option, then the included structure must have been declared with a :type option specifying the same representation type.
If no :type option is involved, then the structure name of the including structure definition becomes the name of a data type, and therefore a valid type specifier recognizable by typep; it becomes a subtype of the included structure. In the above example, astronaut is a subtype of person; hence
(typep (make-astronaut) 'person) ⇒ true
indicating that all operations on persons also work on astronauts.
The structure using :include can specify default values or slot-options for the included slots different from those the included structure specifies, by giving the :include option as:
(:include included-structure-name {slot-description}*)
Each slot-description must have a slot-name that is the same as that of some slot in the included structure. If a slot-description has no slot-initform, then in the new structure the slot has no initial value. Otherwise its initial value form is replaced by the slot-initform in the slot-description. A normally writable slot can be made read-only. If a slot is read-only in the included structure, then it must also be so in the including structure. If a type is supplied for a slot, it must be a subtype of the type specified in the included structure.
For example, if the default age for an astronaut is 45, then
(defstruct (astronaut (:include person (age 45))) helmet-size (favorite-beverage 'tang))
If :include is used with the :type option, then the effect is first to skip over as many representation elements as needed to represent the included structure, then to skip over any additional elements supplied by the :initial-offset option, and then to begin allocation of elements from that point. For example:
(defstruct (binop (:type list) :named (:initial-offset 2)) (operator '? :type symbol) operand-1 operand-2) ⇒ BINOP (defstruct (annotated-binop (:type list) (:initial-offset 3) (:include binop)) commutative associative identity) ⇒ ANNOTATED-BINOP (make-annotated-binop :operator '* :operand-1 'x :operand-2 5 :commutative t :associative t :identity 1) ⇒ (NIL NIL BINOP * X 5 NIL NIL NIL T T 1)
The first two nil elements stem from the :initial-offset of 2 in the definition of binop. The next four elements contain the structure name and three slots for binop. The next three nil elements stem from the :initial-offset of 3 in the definition of annotated-binop. The last three list elements contain the additional slots for an annotated-binop.
:initial-offset instructs defstruct to skip over a certain number of slots before it starts allocating the slots described in the body. This option’s argument is the number of slots defstruct should skip. :initial-offset can be used only if :type is also supplied.
[Reviewer Note by Barmar: What are initial values of the skipped slots?]
:initial-offset allows slots to be allocated beginning at a representational element other than the first. For example, the form
(defstruct (binop (:type list) (:initial-offset 2)) (operator '? :type symbol) operand-1 operand-2) ⇒ BINOP
would result in the following behavior for make-binop:
(make-binop :operator '+ :operand-1 'x :operand-2 5) ⇒ (NIL NIL + X 5) (make-binop :operand-2 4 :operator '*) ⇒ (NIL NIL * NIL 4)
The selector functions binop-operator, binop-operand-1, and binop-operand-2 would be essentially equivalent to third, fourth, and fifth, respectively. Similarly, the form
(defstruct (binop (:type list) :named (:initial-offset 2)) (operator '? :type symbol) operand-1 operand-2) ⇒ BINOP
would result in the following behavior for make-binop:
(make-binop :operator '+ :operand-1 'x :operand-2 5) ⇒ (NIL NIL BINOP + X 5) (make-binop :operand-2 4 :operator '*) ⇒ (NIL NIL BINOP * NIL 4)
The first two nil elements stem from the :initial-offset of 2 in the definition of binop. The next four elements contain the structure name and three slots for binop.
:named specifies that the structure is named. If no :type is supplied, then the structure is always named.
For example:
(defstruct (binop (:type list)) (operator '? :type symbol) operand-1 operand-2) ⇒ BINOP
This defines a constructor function make-binop and three selector functions, namely binop-operator, binop-operand-1, and binop-operand-2. (It does not, however, define a predicate binop-p, for reasons explained below.)
The effect of make-binop is simply to construct a list of length three:
(make-binop :operator '+ :operand-1 'x :operand-2 5) ⇒ (+ X 5) (make-binop :operand-2 4 :operator '*) ⇒ (* NIL 4)
It is just like the function list except that it takes keyword arguments and performs slot defaulting appropriate to the binop conceptual data type. Similarly, the selector functions binop-operator, binop-operand-1, and binop-operand-2 are essentially equivalent to car, cadr, and caddr, respectively. They might not be completely equivalent because, for example, an implementation would be justified in adding error-checking code to ensure that the argument to each selector function is a length-3 list.
binop is a conceptual data type in that it is not made a part of the Common Lisp type system. typep does not recognize binop as a type specifier, and type-of returns list when given a binop structure. There is no way to distinguish a data structure constructed by make-binop from any other list that happens to have the correct structure.
There is not any way to recover the structure name binop from a structure created by make-binop. This can only be done if the structure is named. A named structure has the property that, given an instance of the structure, the structure name (that names the type) can be reliably recovered. For structures defined with no :type option, the structure name actually becomes part of the Common Lisp data-type system. type-of, when applied to such a structure, returns the structure name as the type of the object; typep recognizes the structure name as a valid type specifier.
For structures defined with a :type option, type-of returns a type specifier such as list or (vector t), depending on the type supplied to the :type option. The structure name does not become a valid type specifier. However, if the :named option is also supplied, then the first component of the structure (as created by a defstruct constructor function) always contains the structure name. This allows the structure name to be recovered from an instance of the structure and allows a reasonable predicate for the conceptual type to be defined: the automatically defined name-p predicate for the structure operates by first checking that its argument is of the proper type (list, (vector t), or whatever) and then checking whether the first component contains the appropriate type name.
Consider the binop example shown above, modified only to include the :named option:
(defstruct (binop (:type list) :named) (operator '? :type symbol) operand-1 operand-2) ⇒ BINOP
As before, this defines a constructor function make-binop and three selector functions binop-operator, binop-operand-1, and binop-operand-2. It also defines a predicate binop-p. The effect of make-binop is now to construct a list of length four:
(make-binop :operator '+ :operand-1 'x :operand-2 5) ⇒ (BINOP + X 5) (make-binop :operand-2 4 :operator '*) ⇒ (BINOP * NIL 4)
The structure has the same layout as before except that the structure name binop is included as the first list element. The selector functions binop-operator, binop-operand-1, and binop-operand-2 are essentially equivalent to cadr, caddr, and cadddr, respectively. The predicate binop-p is more or less equivalent to this definition:
(defun binop-p (x) (and (consp x) (eq (car x) 'binop))) ⇒ BINOP-P
The name binop is still not a valid type specifier recognizable to typep, but at least there is a way of distinguishing binop structures from other similarly defined structures.
This option takes one argument, which specifies the name of the type predicate. If the argument is not supplied or if the option itself is not supplied, the name of the predicate is made by concatenating the name of the structure to the string "-P", interning the name in whatever package is current at the time defstruct is expanded. If the argument is provided and is nil, no predicate is defined. A predicate can be defined only if the structure is named; if :type is supplied and :named is not supplied, then :predicate must either be unsupplied or have the value nil.
The :print-function and :print-object options specify that a print-object method for structures of type structure-name should be generated. These options are not synonyms, but do perform a similar service; the choice of which option (:print-function or :print-object) is used affects how the function named printer-name is called. Only one of these options may be used, and these options may be used only if :type is not supplied.
If the :print-function option is used, then when a structure of type structure-name is to be printed, the designated printer function is called on three arguments:
the structure to be printed (a generalized instance of structure-name).
a stream to print to.
an integer indicating the current depth. The magnitude of this integer may vary between implementations; however, it can reliably be compared against *print-level* to determine whether depth abbreviation is appropriate.
Specifying (:print-function printer-name) is approximately equivalent to specifying:
(defmethod print-object ((object structure-name) stream) (funcall (function printer-name) object stream <<current-print-depth>>))
where the <<current-print-depth>> represents the printer’s belief of how deep it is currently printing. It is implementation-dependent whether <<current-print-depth>> is always 0 and *print-level*, if non-nil, is re-bound to successively smaller values as printing descends recursively, or whether current-print-depth varies in value as printing descends recursively and *print-level* remains constant during the same traversal.
If the :print-object option is used, then when a structure of type structure-name is to be printed, the designated printer function is called on two arguments:
the structure to be printed.
the stream to print to.
Specifying (:print-object printer-name) is equivalent to specifying:
(defmethod print-object ((object structure-name) stream) (funcall (function printer-name) object stream))
If no :type option is supplied, and if either a :print-function or a :print-object option is supplied, and if no printer-name is supplied, then a print-object method specialized for structure-name is generated that calls a function that implements the default printing behavior for structures using #S notation; see Printing Structures.
If neither a :print-function nor a :print-object option is supplied, then defstruct does not generate a print-object method specialized for structure-name and some default behavior is inherited either from a structure named in an :include option or from the default behavior for printing structures; see the function print-object and Printing Structures.
When *print-circle* is true, a user-defined print function can print objects to the supplied stream using write, prin1, princ, or format and expect circularities to be detected and printed using the #n# syntax. This applies to methods on print-object in addition to :print-function options. If a user-defined print function prints to a stream other than the one that was supplied, then circularity detection starts over for that stream. See the variable *print-circle*.
:type explicitly specifies the representation to be used for the structure. Its argument must be one of these types:
This produces the same result as specifying (vector t). The structure is represented as a general vector, storing components as vector elements. The first component is vector element 1 if the structure is :named, and element 0 otherwise.
[Reviewer Note by Barmar: Do any implementations create non-simple vectors?]
The structure is represented as a (possibly specialized) vector, storing components as vector elements. Every component must be of a type that can be stored in a vector of the type specified. The first component is vector element 1 if the structure is :named, and element 0 otherwise. The structure can be :named only if the type symbol is a subtype of the supplied element-type.
The structure is represented as a list. The first component is the cadr if the structure is :named, and the car if it is not :named.
Specifying this option has the effect of forcing a specific representation and of forcing the components to be stored in the order specified in defstruct in corresponding successive elements of the specified representation. It also prevents the structure name from becoming a valid type specifier recognizable by typep.
For example:
(defstruct (quux (:type list) :named) x y)
should make a constructor that builds a list exactly like the one that list produces, with quux as its car.
If this type is defined:
(deftype quux () '(satisfies quux-p))
then this form
(typep (make-quux) 'quux)
should return precisely what this one does
(typep (list 'quux nil nil) 'quux)
If :type is not supplied, the structure is represented as an object of type structure-object.
defstruct without a :type option defines a class with the structure name as its name. The metaclass of structure instances is structure-class.
The consequences of redefining a defstruct structure are undefined.
In the case where no defstruct options have been supplied, the following functions are automatically defined to operate on instances of the new structure:
A predicate with the name structure-name-p is defined to test membership in the structure type. The predicate (structure-name-p object) is true if an object is of this type; otherwise it is false. typep can also be used with the name of the new type to test whether an object belongs to the type. Such a function call has the form (typep object 'structure-name).
Reader functions are defined to read the components of the structure. For each slot name, there is a corresponding reader function with the name structure-name-slot-name. This function reads the contents of that slot. Each reader function takes one argument, which is an instance of the structure type. setf can be used with any of these reader functions to alter the slot contents.
A constructor function with the name make-structure-name is defined. This function creates and returns new instances of the structure type.
A copier function with the name copy-structure-name is defined. The copier function takes an object of the structure type and creates a new object of the same type that is a copy of the first. The copier function creates a new structure with the same component entries as the original. Corresponding components of the two structure instances are eql.
If a defstruct form appears as a top level form, the compiler must make the structure type name recognized as a valid type name in subsequent declarations (as for deftype) and make the structure slot readers known to setf. In addition, the compiler must save enough information about the structure type so that further defstruct definitions can use :include in a subsequent deftype in the same file to refer to the structure type name. The functions which defstruct generates are not defined in the compile time environment, although the compiler may save enough information about the functions to code subsequent calls inline. The #S reader macro might or might not recognize the newly defined structure type name at compile time.
An example of a structure definition follows:
(defstruct ship x-position y-position x-velocity y-velocity mass)
This declares that every ship is an object with five named components. The evaluation of this form does the following:
It defines ship-x-position to be a function of one argument, a ship, that returns the x-position of the ship; ship-y-position and the other components are given similar function definitions. These functions are called the access functions, as they are used to access elements of the structure.
ship becomes the name of a type of which instances of ships are elements. ship becomes acceptable to typep, for example; (typep x 'ship) is true if x is a ship and false if x is any object other than a ship.
A function named ship-p of one argument is defined; it is a predicate that is true if its argument is a ship and is false otherwise.
A function called make-ship is defined that, when invoked, creates a data structure with five components, suitable for use with the access functions. Thus executing
(setq ship2 (make-ship))
sets ship2 to a newly created ship object. One can supply the initial values of any desired component in the call to make-ship by using keyword arguments in this way:
(setq ship2 (make-ship :mass *default-ship-mass* :x-position 0 :y-position 0))
This constructs a new ship and initializes three of its components. This function is called the "constructor function" because it constructs a new structure.
A function called copy-ship of one argument is defined that, when given a ship object, creates a new ship object that is a copy of the given one. This function is called the "copier function."
setf can be used to alter the components of a ship:
(setf (ship-x-position ship2) 100)
This alters the x-position of ship2 to be 100. This works because defstruct behaves as if it generates an appropriate defsetf for each access function.
;;; ;;; Example 1 ;;; define town structure type ;;; area, watertowers, firetrucks, population, elevation are its components ;;; (defstruct town area watertowers (firetrucks 1 :type fixnum) ;an initialized slot population (elevation 5128 :read-only t)) ;a slot that can't be changed ⇒ TOWN ;create a town instance (setq town1 (make-town :area 0 :watertowers 0)) ⇒ #S(TOWN...) ;town's predicate recognizes the new instance (town-p town1) ⇒ true ;new town's area is as specified by make-town (town-area town1) ⇒ 0 ;new town's elevation has initial value (town-elevation town1) ⇒ 5128 ;setf recognizes reader function (setf (town-population town1) 99) ⇒ 99 (town-population town1) ⇒ 99 ;copier function makes a copy of town1 (setq town2 (copy-town town1)) ⇒ #S(TOWN...) (= (town-population town1) (town-population town2)) ⇒ true ;since elevation is a read-only slot, its value can be set only ;when the structure is created (setq town3 (make-town :area 0 :watertowers 3 :elevation 1200)) ⇒ #S(TOWN...) ;;; ;;; Example 2 ;;; define clown structure type ;;; this structure uses a nonstandard prefix ;;; (defstruct (clown (:conc-name bozo-)) (nose-color 'red) frizzy-hair-p polkadots) ⇒ CLOWN (setq funny-clown (make-clown)) ⇒ #S(CLOWN) ;use non-default reader name (bozo-nose-color funny-clown) ⇒ RED (defstruct (klown (:constructor make-up-klown) ;similar def using other (:copier clone-klown) ;customizing keywords (:predicate is-a-bozo-p)) nose-color frizzy-hair-p polkadots) ⇒ klown ;custom constructor now exists (fboundp 'make-up-klown) ⇒ true ;;; ;;; Example 3 ;;; define a vehicle structure type ;;; then define a truck structure type that includes ;;; the vehicle structure ;;; (defstruct vehicle name year (diesel t :read-only t)) ⇒ VEHICLE (defstruct (truck (:include vehicle (year 79))) load-limit (axles 6)) ⇒ TRUCK (setq x (make-truck :name 'mac :diesel t :load-limit 17)) ⇒ #S(TRUCK...) ;vehicle readers work on trucks (vehicle-name x) ⇒ MAC ;default taken from :include clause (vehicle-year x) ⇒ 79 (defstruct (pickup (:include truck)) ;pickup type includes truck camper long-bed four-wheel-drive) ⇒ PICKUP (setq x (make-pickup :name 'king :long-bed t)) ⇒ #S(PICKUP...) ;:include default inherited (pickup-year x) ⇒ 79 ;;; ;;; Example 4 ;;; use of BOA constructors ;;; (defstruct (dfs-boa ;BOA constructors (:constructor make-dfs-boa (a b c)) (:constructor create-dfs-boa (a &optional b (c 'cc) &rest d &aux e (f 'ff)))) a b c d e f) ⇒ DFS-BOA ;a, b, and c set by position, and the rest are uninitialized (setq x (make-dfs-boa 1 2 3)) ⇒ #(DFS-BOA...) (dfs-boa-a x) ⇒ 1 ;a and b set, c and f defaulted (setq x (create-dfs-boa 1 2)) ⇒ #(DFS-BOA...) (dfs-boa-b x) ⇒ 2 (eq (dfs-boa-c x) 'cc) ⇒ true ;a, b, and c set, and the rest are collected into d (setq x (create-dfs-boa 1 2 3 4 5 6)) ⇒ #(DFS-BOA...) (dfs-boa-d x) ⇒ (4 5 6)
If any two slot names (whether present directly or inherited by the :include option) are the same under string=, defstruct should signal an error of type program-error.
The consequences are undefined if the included-structure-name does not name a structure type.
documentation; (setf documentation), print-object, setf; psetf, subtypep, type-of, typep, Compilation
The printer-name should observe the values of such printer-control variables as *print-escape*.
The restriction against issuing a warning for type mismatches between a slot-initform and the corresponding slot’s :type option is necessary because a slot-initform must be specified in order to specify slot options; in some cases, no suitable default may exist.
The mechanism by which defstruct arranges for slot accessors to be usable with setf is implementation-dependent; for example, it may use setf functions, setf expanders, or some other implementation-dependent mechanism known to that implementation’s code for setf.
Next: copy-structure, Previous: Structures Dictionary, Up: Structures Dictionary


|
Jump to DART Documentation Main Index |
IMPORTANT:
This document will only render correctly after it has been installed into the DART software
tree - (read the bit about git_to_dart_clm.csh
in intf_DA/dart/shellscripts/README)
This is the DART interface to the Community Land Model (CLM).
Some of this documentation describes how CLM is run under the
Community Earth System Model (CESM)
framework, some of it pertains to
TerrSysMP.
It is strongly recommended that you become familiar with running a
multi-instance experiment in either framework
before you try to run DART/CLM.
TerrSysMP
The TerrSysMP/DART facility uses language and concepts that should be familiar to CESM users.
Please note that TerrSysMP is not distributed in the DART software and must be downloaded and
installed separately.
CLM User's Guide is an excellent reference for CLM.
In the TerrSysMP configuration, CLM executes forecasts for the length of an assimilation cycle,
stops, and writes out restart files (and perhaps history files and even 'vector' history files).
This GREATLY simplifies the traditional DART workflow, but it means
TerrSysMP has to stop and write out a restart file every time an assimilation is required.
Since some output normally happens at every assimilation interval, the extra time required to completely stop
is minimal for all but the most trivial configurations. Reading from restart files allows DART to be able
to flexibly adapt to new versions of the models and generally requires no additional coding.
DART does not advance CLM. TerrSysMP is responsible for that. DART requires a CLM
restart file at every time an observation is desired. It is up to you to run TerrSysMP
such that it stops when you want to harvest the observations.
A single instance of the CLM state is completely sufficient for running DART's
perfect_model_obs program. DART provides a template CESM
setup script (CESM1_1_1_setup_pmo) and a script
(perfect_model.csh) to execute the DART programs
required to harvest the observations. The input observation sequence files
must be created a priori and staged in a location that must be made available
to the perfect_model.csh script.
| Script | Description |
|---|---|
| CESM1_1_1_pmo_setup | runs a single instance of CLM to harvest synthetic observations for an OSSE or
"perfect model" experiment. It requires a single CLM state from a previous
experiment and uses a specified DATM stream for forcing. This parallels an
assimilation experiment in that in the multi-instance setting each CLM instance
may use (should use?) a unique DATM forcing. This script has almost nothing to
do with DART. There is one (trivial) section that records some configuration
information in the DART setup script, but that's about it. This script should
initially be run without DART to ensure a working CESM environment.
As of (V7195) 3 October 2014, this script demonstrates how to create 'vector'-based CLM history files (which requires a bugfix) and has an option to use a bugfixed snow grain-size code. http://bugs.cgd.ucar.edu/show_bug.cgi?id=1730 http://bugs.cgd.ucar.edu/show_bug.cgi?id=1934 |
| CESM1_2_1_setup_pmo | Is functionally identical to CESM1_1_1_setup_pmo but is appropriate for the the CESM 1_2_1 release, which supports both CLM 4 and CLM 4.5. |
| CESM1_1_1_hybrid_initial | runs a multi-instance CLM experiment and can be used to perform a free run or
'open loop' experiment. By default, each CLM instance uses a unique DATM forcing.
This script also has almost nothing to do with DART. There is one (trivial)
section that records some configuration information in the DART setup script,
but that's about it. This script should initially be run without DART to ensure
a working CESM.
As of (V7195) 3 October 2014, this script demonstrates how to create 'vector'-based CLM history files (which requires a bugfix) and has an option to use a bugfixed snow grain-size code. http://bugs.cgd.ucar.edu/show_bug.cgi?id=1730 http://bugs.cgd.ucar.edu/show_bug.cgi?id=1934 |
| CESM1_2_1_setup_hybrid | Is functionally identical to CESM1_1_1_setup_hybrid but is appropriate for the the CESM 1_2_1 release, which supports both CLM 4 and CLM 4.5. |
| CESM_DART_config | augments a CESM case with the bits and pieces required to run DART. When either CESM1_?_1_setup_pmo or CESM1_?_1_setup_hybrid gets executed, CESM_DART_config gets copied to the CESM "caseroot" directory. It is designed such that you can execute it at any time during a CESM experiment. When you do execute it, it will build the DART executables and copy them into the CESM "bld" directory, stage the run-time configurable input.nml in the "caseroot" directory, etc. and also modifies the CESM case.run script to call the DART scripts for assimilation or to harvest synthetic observations. |
In addition to the script above, there are a couple scripts that will either perform an assimilation (assimilate.csh) or harvest observations for a perfect model experiment (perfect_model.csh). These scripts are designed to work on several compute platforms although they require configuration, mainly to indicate the location of the DART observation sequence files on your system.
"Simple" observations like snowcover fraction come directly from the DART
state. It is possible to configure the CLM history files to contain the CLM
estimates of some quantities (mostly flux tower observations e.g,
net ecosystem production, sensible heat
flux, latent heat flux) that are very complicated combinations of
portions of the CLM state. The forward observation operators for these
flux tower observations read these quantities from the CLM
.h1. history file. The smaller the CLM gridcell,
the more likely it seems that these values will agree with point observations.
The prior and posterior values for these will naturally be
identical as the history file is unchanged by the assimilation.
Configuring the CLM user_nl_clm files to output the desired quantities
must be done at the first execution of CLM. As soon as CONTINUE_RUN=TRUE,
the namelist values for history file generation are ignored. Because the
history file creation is very flexible, some additional information must
be passed to DART to construct the filename of the
.h1. history file needed for any particular time.
The DART state vector may be constructed in a much more flexible way.
Variables from two different CLM history files may also be incorporated directly
into the DART state - which should GREATLY speed up the forward observation
operators - and allow the observation operators to be constructed in a more
flexible manner so that they can be used by any model capable of providing
required inputs. It is now possible to read some variables from the restart
file, some variables from a traditional history file, and some from a
'vector-based' history file that has the same structure (gridcell/landunit/column/pft)
as the restart file. This should allow more accurate forward observation operators
since the quantities are not gridcell-averaged a priori.
Another namelist item has been added clm_vector_history_filename
to support the concept that two history files can be supported. My intent
was to have the original history file (required for grid metadata) and another for support
of vector-based quantities in support of forward observation operators.
Upon reflection, I'm not sure I need two different history files - BUT - I'm sure
there will be a situation where it comes in handy.
The new namelist specification of what goes into the DART state vector includes
the ability to specify if the quantity should have a lower bound, upper bound,
or both, what file the variable should be read from, and if the variable should be
modified by the assimilation or not. Only variables in the CLM restart file will
be candidates for updating. No CLM history files are modified. It is important
to know that the variables in the DART diagnostic files Prior_Diag.nc
and Posterior_Diag.nc will contain the unbounded versions of ALL the
variables specied in clm_variables.
The example input.nml model_nml demonstrates
how to construct the DART state vector. The following table explains in detail each
entry for clm_variables:
| Column 1 | Column 2 | Column 3 | Column 4 | Column 5 | Column 6 |
|---|---|---|---|---|---|
| Variable name | DART KIND | minimum | maximum | filename | update |
| Column 1 | Variable name | This is the CLM variable name as it appears in the CLM netCDF file. |
| Column 2 | DART KIND | This is the character string of the corresponding DART KIND. |
| Column 3 | minimum | If the variable is to be updated in the CLM restart file, this specifies the minimum value. If set to 'NA', there is no minimum value. |
| Column 4 | maximum | If the variable is to be updated in the CLM restart file, this specifies the maximum value. If set to 'NA', there is no maximum value. |
| Column 5 | filename | This specifies which file should be used to obtain the variable. 'restart' => clm_restart_filename 'history' => clm_history_filename 'vector' => clm_vector_history_filename |
| Column 6 | update | If the variable comes from the restart file, it may be updated after the assimilation. 'UPDATE' => the variable in the restart file is updated. 'NO_COPY_BACK' => the variable in the restart file remains unchanged. |
The following are only meant to be examples - they are not scientifically validated. Some of these that are UPDATED are probably diagnostic quantities, Some of these that should be updated may be marked NO_COPY_BACK. There are multiple choices for some DART kinds. This list is by no means complete.
'livecrootc', 'KIND_ROOT_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'deadcrootc', 'KIND_ROOT_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'livestemc', 'KIND_STEM_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'deadstemc', 'KIND_STEM_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'livecrootn', 'KIND_ROOT_NITROGEN', 'NA', 'NA', 'restart', 'UPDATE', 'deadcrootn', 'KIND_ROOT_NITROGEN', 'NA', 'NA', 'restart', 'UPDATE', 'livestemn', 'KIND_STEM_NITROGEN', 'NA', 'NA', 'restart', 'UPDATE', 'deadstemn', 'KIND_STEM_NITROGEN', 'NA', 'NA', 'restart', 'UPDATE', 'litr1c', 'KIND_LEAF_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'litr2c', 'KIND_LEAF_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'litr3c', 'KIND_LEAF_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'soil1c', 'KIND_SOIL_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'soil2c', 'KIND_SOIL_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'soil3c', 'KIND_SOIL_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'soil4c', 'KIND_SOIL_CARBON', 'NA', 'NA', 'restart', 'UPDATE', 'fabd', 'KIND_FPAR_DIRECT', 'NA', 'NA', 'restart', 'UPDATE', 'fabi', 'KIND_FPAR_DIFFUSE', 'NA', 'NA', 'restart', 'UPDATE', 'T_VEG', 'KIND_VEGETATION_TEMPERATURE', 'NA', 'NA', 'restart', 'UPDATE', 'fabd_sun_z', 'KIND_FPAR_SUNLIT_DIRECT', 'NA', 'NA', 'restart', 'UPDATE', 'fabd_sha_z', 'KIND_FPAR_SUNLIT_DIFFUSE', 'NA', 'NA', 'restart', 'UPDATE', 'fabi_sun_z', 'KIND_FPAR_SHADED_DIRECT', 'NA', 'NA', 'restart', 'UPDATE', 'fabi_sha_z', 'KIND_FPAR_SHADED_DIFFUSE', 'NA', 'NA', 'restart', 'UPDATE', 'elai', 'KIND_LEAF_AREA_INDEX', 'NA', 'NA', 'restart', 'UPDATE',
Only the first variable for a DART kind in the clm_variables list will be used for the forward observation operator. The following is perfectly legal (for CLM4, at least):
clm_variables = 'LAIP_VALUE', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'restart' , 'UPDATE', 'tlai', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'restart' , 'UPDATE', 'elai', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'restart' , 'UPDATE', 'ELAI', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'LAISHA', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'LAISUN', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'TLAI', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'TLAI', 'KIND_LEAF_AREA_INDEX', 'NA' , 'NA' , 'vector' , 'NO_COPY_BACK' 'FSRVDLN', 'KIND_RADIATION_VISIBLE_UP', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'FSRNDLN', 'KIND_RADIATION_NEAR_IR_UP', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'FSDSVDLN', 'KIND_RADIATION_VISIBLE_DOWN', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'FSDSNDLN', 'KIND_RADIATION_NEAR_IR_DOWN', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'PBOT', 'KIND_SURFACE_PRESSURE', '0.0', 'NA' , 'vector' , 'NO_COPY_BACK', 'TBOT', 'KIND_TEMPERATURE', 'NA' , 'NA' , 'vector' , 'NO_COPY_BACK' /
however, only LAIP_VALUE will be used to calculate the LAI when an observation of LAI is encountered. All the other LAI variables in the DART state will be modified by the assimilation based on the relationship of LAIP_VALUE and the observation. Those coming from the restart file and marked 'UPDATE' will be updated in the CLM restart file.
Snow data assimilation is tricky business. CLM has different snow schemes and
representations over lakes than on land. Glaciers are another matter.
CLM4 is different than CLM4.5. Different ensemble members (CESM instances) may
have different numbers of snow layers. For all these reasons and more, we strongly
suggest that you thoroughly examine the DART update methodology (see routine
model_mod.f90 update_snow() )
and your results.
It is worth knowing that DART does not make snow if there is none present.
Furthermore, if one or more ensemble members/instances does not have snow
and the other ensemble members do have snow, the system is ill-determined. In this case,
DART simply does nothing to the CLM column in question. The posterior and the prior for
that particular column is the same for all ensemble members. Extending DART such that
snow is handled in a better manner would be a great DA research effort, in my opinion.
When all the ensemble members in a CLM column have snow, a description of the
strategy is as follows: The CLM variable H2OSNO must be part of the
DART state and must be flagged as UPDATE. The increments are calculated in the usual way.
The original proportions of snow water and ice in each layer are preserved
as the increment is distributed among the prognostic variables for snow in CLM:
SNOWDP, DZSNO, H2OSOI_LIQ, and H2OSOI_ICE.
The exact algorithm is in the update_snow() routine.
Note that SNOWDP, DZSNO, H2OSOI_LIQ, and H2OSOI_ICE
do not need to be part of the DART state vector. In fact, if they are part of the
DART state vector, the posterior estimates of these variables is not conveyed
to the CLM restart file because it may clash with the estimates from the
update_snow() routine. The posterior estimates of these
variables will/may be used for other observation operators, however.
These namelists are read from the file input.nml. Namelists start with an ampersand '&' and terminate with a slash '/'. Character strings that contain a '/' must be enclosed in quotes to prevent them from prematurely terminating the namelist. Please note that the values listed here are the default values. A more representative example follows after this description.
&model_nml clm_file_s = 'clm_restart_s.nc', clm_restart_filename = 'clm_restart.nc', clm_history_filename = 'clm_history.nc', clm_vector_history_filename = 'clm_vector_history.nc', assimilation_period_days = 2, assimilation_period_seconds = 0, model_perturbation_amplitude = 0.2, calendar = 'Gregorian', debug = 0 clm_variables = '', /
| Item | Type | Description |
|---|---|---|
| clm_file_s | character(len=256) | this is the filename of a CLM restart file from the beginning of the experiment. This file is used to create a resource file (normally called clm_prior_time.txt) for ParFlow. Usually, a specific CLM restart file is linked to the name specified in clm_file_s. |
| clm_restart_filename | character(len=256) | this is the filename of the CLM restart file. The DART scripts resolve linking the specific CLM restart file to this generic name. This file provides the elements used to make up the DART state vector. The variables are in their original landunit, column, and PFT-based representations. |
| clm_history_filename | character(len=256) | this is the filename of the CLM .h0. history file. The DART scripts resolve linking the specific CLM history file to this generic name. Some of the metadata needed for the DART/CLM interfaces is contained only in this history file, so it is needed for all DART routines. |
| clm_vector_history_filename | character(len=256) | this is the filename of a second CLM history file. The DART scripts resolve linking the specific CLM history file to this generic name. The default setup scripts actually create 3 separate CLM history files, the .h2. ones are linked to this filename. It is possible to create this history file at the same resolution as the restart file, which should make for better forward operators. It is only needed if some of the variables specified in clm_variables come from this file. |
| assimilation_period_days, assimilation_period_seconds |
integer | Combined, these specify the width of the assimilation window. The current model time is used as the center time of the assimilation window. All observations in the assimilation window are assimilated. BEWARE: if you put observations that occur before the beginning of the assimilation_period, DART will error out because it cannot move the model 'back in time' to process these observations. |
| model_perturbation_amplitude | real(r8) | Required by the DART interfaces, but not used by CLM. |
| calendar | character(len=32) | string specifying the calendar to use with DART. The CLM dates will be interpreted with this same calendar. For assimilations with real observations, this should be 'Gregorian'. |
| debug | integer | Set to 0 (zero) for minimal output. Successively higher values generate successively more output. Not all values are important, however. It seems I've only used values [3,6,7,8]. Go figure. |
| clm_variables | character(:,6) | Strings that identify the CLM variables, their DART
kind, the min & max values, what file to read from, and whether
or not the file should be updated after the assimilation.
Only CLM variable names in the CLM restart file are valid.
The DART kind must be one found in the
DART/obs_kind/obs_kind_mod.f90
AFTER it gets built by preprocess.
Most of the land observation kinds are specified by
DART/obs_def/obs_def_tower_mod.f90, so it should
be specified in the preprocess_nml:input_files variable.
Each variable must have 6 entries.
|
This is a much more realistic example of a DART-CLM namelist and will accomodate a wide variety of forward operators. In the TerrSysMP configuration, only the soil temperature needs to be updated, the rest of the variables are used for forward operator calculation only.
&model_nml clm_restart_filename = 'clm_restart.nc' clm_history_filename = 'clm_history.nc' clm_file_s = 'clm_restart_s.nc' clm_vector_history_filename = 'clm_vector_history.nc' assimilation_period_days = 0 assimilation_period_seconds = 21400 model_perturbation_amplitude = 0.2 calendar = 'Gregorian' debug = 0 clm_variables = 'T_SOISNO', 'KIND_SOIL_TEMPERATURE', 'NA' , 'NA' , 'restart' , 'UPDATE', 'frac_sno', 'KIND_SNOWCOVER_FRAC', '0.0', '1.0', 'restart' , 'NO_COPY_BACK', 'H2OSNO', 'KIND_SNOW_WATER', '0.0', 'NA' , 'restart' , 'NO_COPY_BACK', 'H2OSOI_LIQ', 'KIND_LIQUID_WATER', '0.0', 'NA' , 'restart' , 'NO_COPY_BACK', 'H2OSOI_ICE', 'KIND_ICE', '0.0', 'NA' , 'restart' , 'NO_COPY_BACK', 'tsai', 'KIND_STEM_AREA_INDEX', '0.0', 'NA' , 'restart' , 'NO_COPY_BACK', 'tlai', 'KIND_LEAF_AREA_INDEX', '0.0', 'NA' , 'restart' , 'NO_COPY_BACK', 'TV', 'KIND_VEGETATION_TEMPERATURE', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'Q2M', 'KIND_SPECIFIC_HUMIDITY', '0.0', 'NA' , 'history' , 'NO_COPY_BACK', 'FSRVDLN', 'KIND_RADIATION_VISIBLE_UP', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'FSRNDLN', 'KIND_RADIATION_NEAR_IR_UP', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'FSDSVDLN', 'KIND_RADIATION_VISIBLE_DOWN', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'FSDSNDLN', 'KIND_RADIATION_NEAR_IR_DOWN', 'NA' , 'NA' , 'history' , 'NO_COPY_BACK', 'PBOT', 'KIND_SURFACE_PRESSURE', '0.0', 'NA' , 'vector' , 'NO_COPY_BACK', 'TBOT', 'KIND_TEMPERATURE', 'NA' , 'NA' , 'vector' , 'NO_COPY_BACK' /
&obs_def_tower_nml casename = '../clm_dart', hist_nhtfrq = -24, debug = .false. /
| Item | Type | Description |
|---|---|---|
| casename | character(len=256) | this is the name of the CESM case. It is used by the forward observation operators to help construct the filename of the CLM .h1. history files for the flux tower observations. When the input.nml gets staged in the CASEROOT directory by CESM_DART_config, the appropriate value should automatically be inserted. |
| hist_nhtfrq | integer | this is the same value as in the CLM documentation. A negative value indicates the number of hours contained in the .h1. file. This value is needed to constuct the right .h1. filename. When the input.nml gets staged in the CASEROOT directory by CESM_DART_config, the appropriate value should automatically be inserted. Due to the large number of ways of specifying the CLM history file information, the correct value here is very dependent on how the case was configured. You would be wise to check it. |
| debug | logical | Set to .false. for minimal output. |
types_mod time_manager_mod threed_sphere/location_mod utilities_mod obs_kind_mod obs_def_tower_mod random_seq_mod
A note about documentation style. Optional arguments are enclosed in brackets [like this].
integer :: get_model_size
Returns the length of the model state vector.
| model_size | The length of the model state vector. |
real(r8), dimension(:), intent(inout) :: x type(time_type), intent(in) :: time
Advances the model for a single time step. The time associated with the initial model state is also input although it is not used for the computation.
| x | State vector of length model_size. |
| time | Specifies time of the initial model state. |
integer, intent(in) :: index_in type(location_type), intent(out) :: location integer, optional, intent(out) :: var_type
Returns metadata about a given element, indexed by index_in, in the model state vector. The location defines where the state variable is located.
| index_in | Index of state vector element about which information is requested. |
| location | The location of state variable element. |
| var_type | The generic DART kind of the state variable element. |
real(r8), dimension(:), intent(in) :: x type(location_type), intent(in) :: location integer, intent(in) :: itype real(r8), intent(out) :: obs_val integer, intent(out) :: istatus
Given model state, returns the value interpolated to a given location.
| x | A model state vector. |
| location | Location to which to interpolate. |
| itype | Not used. |
| obs_val | The interpolated value from the model. |
| istatus | If the interpolation was successful istatus = 0. If istatus /= 0 the interpolation failed. Values less than zero are reserved for DART. |
type(time_type) :: get_model_time_step
Returns the time step (forecast length) of the model;
| var | Smallest time step of model. |
Used for runtime initialization of model; reads namelist, initializes model parameters, etc. This is the first call made to the model by any DART-compliant assimilation routine.
A stub.
type(time_type), intent(out) :: time
Returns the time at which the model will start if no input initial conditions are to be used. This is used to spin-up the model from rest.
| time | Initial model time. |
real(r8), dimension(:), intent(out) :: x
Returns default initial conditions for the model; generally used for spinning up initial model states.
| x | Initial conditions for state vector. |
integer :: nc_write_model_atts integer, intent(in) :: ncFileID
Function to write model specific attributes to a netCDF file. At present, DART is using the NetCDF format to output diagnostic information. This is not a requirement, and models could choose to provide output in other formats. This function writes the metadata associated with the model to a NetCDF file opened to a file identified by ncFileID.
| ncFileID | Integer file descriptor to previously-opened netCDF file. |
| ierr | Returns a 0 for successful completion. |
integer :: nc_write_model_vars integer, intent(in) :: ncFileID real(r8), dimension(:), intent(in) :: statevec integer, intent(in) :: copyindex integer, intent(in) :: timeindex
Writes a copy of the state variables to a netCDF file. Multiple copies of the state for a given time are supported, allowing, for instance, a single file to include multiple ensemble estimates of the state.
| ncFileID | file descriptor to previously-opened netCDF file. |
| statevec | A model state vector. |
| copyindex | Integer index of copy to be written. |
| timeindex | The timestep counter for the given state. |
| ierr | Returns 0 for normal completion. |
real(r8), dimension(:), intent(in) :: state real(r8), dimension(:), intent(out) :: pert_state logical, intent(out) :: interf_provided
Given a model state, produces a perturbed model state.
| state | State vector to be perturbed. |
| pert_state | Perturbed state vector: NOT returned. |
| interf_provided | Returned false; interface is not implemented. |
type(get_close_type), intent(inout) :: gc real(r8), intent(in) :: maxdist
In distance computations any two locations closer than the given maxdist will be considered close by the get_close_obs() routine. Pass-through to the 3D Sphere locations module. See get_close_maxdist_init() for the documentation of this subroutine.
type(get_close_type), intent(inout) :: gc integer, intent(in) :: num type(location_type), intent(in) :: obs(num)
Pass-through to the 3D Sphere locations module. See get_close_obs_init() for the documentation of this subroutine.
type(get_close_type), intent(in) :: gc type(location_type), intent(in) :: base_obs_loc integer, intent(in) :: base_obs_kind type(location_type), intent(in) :: obs(:) integer, intent(in) :: obs_kind(:) integer, intent(out) :: num_close integer, intent(out) :: close_ind(:) real(r8), optional, intent(out) :: dist(:)
Pass-through to the 3D Sphere locations module. See get_close_obs() for the documentation of this subroutine.
real(r8), dimension(:), intent(in) :: ens_mean
A NULL INTERFACE in this model.
| ens_mean | State vector containing the ensemble mean. |
integer, intent(out) :: num_lon, num_lat, num_lev
Returns the number of longitudes, latitudes, and total number of levels in the CLM state.
| num_lon | The number of longitude grid cells in the CLM state. This comes from the CLM history file. |
| num_lat | The number of latitude grid cells in the CLM state. This comes from the CLM history file. |
| num_lev | The number of levels grid cells in the CLM state. This comes from 'nlevtot' in the CLM restart file. |
real(r8), intent(inout) :: state_vector(:) type(time_type), intent(out) :: restart_time
Reads the current time and state variables from CLM netCDF
file(s) and packs them into a DART state vector. This MUST happen
in the same fashion as the metadata arrays are built. The variables
are specified by model_nml:clm_variables.
Each variable specifies its own file of origin.
If there are multiple times in the file of origin, only the time that
matches the restart file are used.
| state_vector | The DART state vector. |
| restart_time | The valid time of the CLM state. |
real(r8), intent(in) :: state_vector(:) character(len=*), intent(in) :: filename type(time_type), intent(in) :: dart_time
This routine updates the CLM restart file with the posterior state from the assimilation. Some CLM variables that are useful to include in the DART state (frac_sno, for example) are diagnostic quantities and are not used for subsequent model advances. The known diagnostic variables are NOT updated. If the values created by the assimilation are outside physical bounds, or if the original CLM value was 'missing', the vector_to_prog_var() subroutine ensures that the values in the original CLM restart file are not updated.
| state_vector | The DART state vector containing the state modified by the assimilation. |
| filename | The name of the CLM restart file. The contents of some of the variables will be overwritten with new values. |
| dart_time | The valid time of the DART state. This has to match the time in the CLM restart file. |
character(len=*), intent(out) :: filename
provides access to the name of the CLM restart file to routines outside the scope of this module.
| filename | The name of the CLM restart file. |
integer, intent(in) :: file_handle character(len=*), intent(in) :: file_handle type(time_type) :: get_state_time
This routine has two interfaces - one for an integer input, one for a filename. They both return the valid time of the model state contained in the file. The file referenced is the CLM restart file in netCDF format.
| file_handle | If specified as an integer, it must be the netCDF file identifier from nf90_open(). If specified as a filename, the name of the netCDF file. |
| time | A DART time-type that contains the valid time of the model state in the CLM restart file. |
real(r8), intent(in) :: x(:) type(location_type), intent(in) :: location character(len=*), intent(in) :: varstring real(r8), intent(out) :: interp_val integer, intent(out) :: istatus
Calculate the value of quantity at depth. The gridcell value at the levels above and below the depth of interest are calculated and then the value for the desired depth is linearly interpolated. Each gridcell value is an area-weighted value of an unknown number of column- or pft-based quantities. This is one of the workhorse routines for model_interpolate().
| x | The DART state vector. |
| location | The location of the desired quantity. |
| varstring | The CLM variable of interest - this must be part of the DART state. e.g, T_SOISNO, H2OSOI_LIQ, H2OSOI_ICE ... |
| interp_val | The quantity at the location of interest. |
| istatus | error code. 0 (zero) indicates a successful interpolation. |
real(r8), intent(in) :: x(:) type(location_type), intent(in) :: location character(len=*), intent(in) :: varstring real(r8), intent(out) :: interp_val integer, intent(out) :: istatus
Calculate the value of a CLM variable in the DART state vector given a location. Since the CLM location information is only available at the gridcell level, all the columns in a gridcell are area-weighted to derive the value for the location. This is one of the workhorse routines for model_interpolate(), and only select CLM variables are currently supported. Only CLM variables that have no vertical levels may use this routine.
| x | The DART state vector. |
| location | The location of the desired quantity. |
| varstring | The CLM variable of interest - this must be part of the DART state. e.g, frac_sno, leafc, ZWT ... |
| interp_val | The quantity at the location of interest. |
| istatus | error code. 0 (zero) indicates a successful interpolation. |
character(len=*), intent(in) :: varstring
This is a utility routine that helps identify how many land units,columns, or PFTs are in each gridcell for a particular variable. Helps answer exploratory questions about which gridcells are appropriate to test code. The CLM variable is read from the CLM restart file.
| varstring | The CLM variable name of interest. |
integer, intent(in) :: ncid character(len=*), intent(in) :: varname real(r8), dimension(:), intent(out) :: datmat real(r8), dimension(:,:), intent(out) :: datmat
Reads a 1D or 2D variable of 'any' type from a netCDF file and processes and applies the offset/scale/FillValue attributes correctly.
| ncid | The netCDF file identifier to an open file. ncid is the output from a nf90_open() call. |
| varname | The name of the netCDF variable of interest. The variables can be integers, floats, or doubles. |
| datmat | The shape of datmat must match the shape of the netCDF variable. Only 1D or 2D variables are currently supported. |
integer :: get_model_time
Returns the valid time of the model state vector.
| model_time | The valid time of the model state vector. |
| filename | purpose |
|---|---|
| input.nml | to read the model_mod namelist |
| clm_restart.nc | both read and modified by the CLM model_mod |
| clm_history.nc | read by the CLM model_mod for metadata purposes. |
| *.h1.* history files | may be read by the obs_def_tower_mod for observation operator purposes. |
| dart_log.out | the run-time diagnostic output |
| dart_log.nml | the record of all the namelists actually USED - contains the default values |
CLM User's Guide is an excellent reference for CLM.
| Routine | Message | Comment |
|---|---|---|
| nc_write_model_atts nc_write_model_vars |
Various netCDF-f90 interface error messages | From one of the netCDF calls in the named routine |
none at this time
Almost too many to list.
N/A
DART software - Copyright 2004 - 2013 UCAR.
This open source software is provided by UCAR, "as is",
without charge, subject to all terms of use at
http://www.image.ucar.edu/DAReS/DART/DART_download
| Contact: | DART core group |
| Revision: | $Revision: 6420 $ |
| Source: | $URL: https://proxy.subversion.ucar.edu/DAReS/DART/releases/Lanai/models/clm/model_mod.html $ |
| Change Date: | $Date: 2013-08-23 01:44:03 +0200 (Fri, 23 Aug 2013) $ |
| Change history: | try "svn log" or "svn diff" |


Find a new friend
Name
Picture
Survey
Choose a number one through five
Question 1
1
2
3
4
5
Question 2
1
2
3
4
5
Question 3
1
2
3
4
5
Question 4
1
2
3
4
5
Question 5
1
2
3
4
5
Question 6
1
2
3
4
5
Question 7
1
2
3
4
5
Submit
×
×
Your friends!


From:Victor Lamadrid To:Robert Allwein; Scott Neal Sent:2017-01-11T04:42:44.0000000Z Subject:FW: New Filters
Here are the filters for Sitara Position manager for NE and SE pipes. Get
out of Position managers, launch the appropriate filters below. When you
re-open Sitara Position mgr, look under Open on the menu bar and the 2
filters should be there. Hit ok and the filter should apply to your position
mgr. THANKS
-----Original Message-----
From: Grant, George
Sent: Tuesday, May 08, 2001 9:44 AM
To: Lamadrid, Victor; Neal, Scott
Subject: New Filters
Here are some new NE and SE pipe filters.
Remember that you must be out of Position Manager when you launch the
attachments.
Thanks
GG
***********
EDRM Enron Email Data Set has been produced in EML, PST and NSF format by ZL Technologies, Inc. This Data Set is licensed under a Creative Commons Attribution 3.0 United States License <http://creativecommons.org/licenses/by/3.0/us/> . To provide attribution, please cite to "ZL Technologies, Inc. (http://www.zlti.com)."
***********
California


All states have seen a decrease in previous years in the percent of residents uninsured. This primarily occurred in 2014 and 2015 when much of the Affordable Care Act came into effect.
New Mexico saw the greatest absolute decrease during this time. It more than halved its uninsured rate, from 24% in 2008 to 11% in 2018.
Massachusetts implemented major health care reform in 2006 and entered this period with an uninsured rate much lower than any other state. It has changed little since 2008.
Meanwhile, Texas both started and ended this period with the highest uninsured rate in the country.
Under the Affordable Care Act, states had the option to expand eligibility for Medicaid. By June 2019, these 34 states had chosen to do so.
The states that haven't expanded Medicaid are generally being left behind in terms of the uninsured rate.


Deep Learning Concept 3: Learning Rate
What is a learning rate?
Learning rate is a hyper-parameter that controls how much we are adjusting the weights of our network with respect to the loss gradient
Why is learning rate important?
Learning rate affects how quickly our model can converge to a local minima. Choosing a bad learning rate can results in network either fail to train or take much longer to converge.
How to choose the best learning rate?
First we need to find the optimal learning rate range. The idea is that when learning rate is too low, the loss may also decrease very slow. When it gets into optimal range, the loss will drop quickly and when it gets out of optimal range, the loss will bounce around and even diverge from minima. In this way, we can know what is the optimal range. Then after that, during training there are two way we can automatically adjust the learning rate:
- learning rate annealing: start with relatively high learning rate and then gradually lowering the learning rate during training. The idea is that we can quickly get to the area of local minima and then find the local minima through small learning rate
- Cycle learning rate: initially proposed in this paper. The author proposed a cyclical learning rate schdule which bounced between two values. It is a triangular update with either fixed cyclic decay or an exponential cyclic decay.


{% extends "parent.html" %} {% block title %}{{ presentation.title }}{% endblock %} {% block page_header %}
This presentation has no description.
{% endif %}{% if presentation.public %} This presentation is public. All users can see when it is being presented. {% else %} This presentation is private and is only available to users with the link. {% endif %}


0
How
are you feeling?
How is it everyting going
How can you stay positive
How can you run away from negative
How can you stay away from shyness
1
What
is going on?
What is psychology
What are the phnomena in today
What is the solution of sadness
What is the effective way to achieve hapiness
2


38yo Man Throws Rocks at Kindergarten Because He Can’t Stand The Kids Singing
by Husna HalimTap to listen to this article instead: 🔊 Listen to Post
Kids. No matter how much you love them, they can have their moments where the only word to describe them is annoying.
According to Coconuts, a kindergarten in Bekasi, West Java received a rain of stones after a guy who lived in the neighbourhood became so annoyed by the singing of the students that he started to throw rocks at the school.
Cibarusah Police Chief Sukarman said in a statement that the event allegedly took place on Wednesday (Nov 13th) morning when a 38-year-old man known as Jaya walked up to the kindergarten in a rage.
“The kids in the Islamic kindergarten were singing and learning. Then, a witness saw the culprit approach the school and throw rocks at it twice,”
“The suspect shouted (possibly at a teacher), ‘You’re too noisy! You’re disturbing my rest!’”
Sukarman stated that Jaya only threw rocks at the kindergarten’s fence, so the incident went by without anyone getting injured. It did scare the kids a little, but the teachers acted quickly and took the kids back inside their classroom to keep them safe.
“No child was traumatised,” he said.
Although the incident is still under investigation, Jaya may be charged for causing an unpleasant atmosphere under Indonesia’s criminal code, and he could receive a punishment of up to one year in prison.
Fortunately for Jaya, the teacher who reported the incident to the police did not press charges against him. A local official said that both the suspect and a representative of the teachers will have a mediation session soon, and the kindergarten is ready to forgive Jaya as long as he promises not to repeat his outburst.
Maybe the man has never dealt with kids before or maybe he was really tired. Hopefully, both sides figure out a resolution!
Also read: Kind M’sian Man Pays For a Kid’s Kindergarten Graduation Photos As His Father Couldn’t Afford It


HTML5 + Javascript asyncronous file upload.
v. 1 - Massimo Cassandro - (c) 2017/2019
Fileuploader automates and simplifies uploading files to HTML pages.
Uploads are performed asynchronously via an Ajax call to a server-side script that must register the file and return a JSON string.
Although the default settings are based on Bootstrap 4, FileUploader is entirely and easily configurable from scratch and can be adapted to any layout.


Across: 1. Just getting adjusted with it - a zinc mail coat! (15) 9. Rare rum - it is distilled in snake-inhabited facility (9) 10. Prance about, rejecting the right to fruit (5) 11. Standing, about to put point (6) 13. Melodic sound of pager ... I go off (8) 15. Human ... capable of being friendly? (10) 16. It can help get a grip on your bad habit (4) 18. Big book about a source of drunkenness? (4) 19. Europe at peak of abstract art - the norm (10) 21. He questioned our use as players (8) 22. Delete brief swearing by star (6) 25. I am lost in exotic Thai country (5) 26. Wild cat zoning in on it (9) 27. Ever causing trouble, has loan torn faction to shreds? (15) Down: 1. Peculiar harm in photo crop making them look like us (15) 2. Scaremonger's device for moving people (3) 3. Back in the inferno, it can invoke stillness (8) 4. Eager for a movie? (4) 5. Limit Mary to drunkenness and various forms of 16 ac. (10) 6. Eve of the fall saw such appealing fruit (6) 7. Getting around, none noticing? (9) 8. Private fool above negative thinking (15) 12. Insecure opt out of harassment (11) 14. Islander is very foolish with a fuel container (10) 17. Oddly German fife in this Italian public display (8) 20. Are his bits more gray? (6) 23. Agrarian reform discards a luxury car once more (5) 24. Agrarian reform - rain taken from city (4)